I think that answer is "you are not supposed to do that" because there is no documentation for the slots of sensors_chip_name. It could work by luck in your C test case if the uninitialized name slot points to a null byte.
__Martin >>>>> On Thu, 26 Apr 2018 20:16:43 -0700, Elliott Johnson said: > > Hello, > > If this is not the correct list to report a user error, I apologize and > will happily redirect my question where ever suitable. > > I've been using cffi to make a trivial library to libsensors > https://github.com/groeck/lm-sensors and am getting an odd memory fault > error when referencing a string value from a groveled struct. After > hitting my head against a wall for a day and a half, I thought I'd ask > in case it's a simple mistake. > > Here's my information: > > Running a 64 bit linux install. My local version of the libsensors > library is as follows: > > > elliott@desktop ~ $ file /usr/lib64/libsensors.so.4.4.0 > > /usr/lib64/libsensors.so.4.4.0: ELF 64-bit LSB shared object, x86-64, > > version 1 (SYSV), dynamically linked, stripped > > elliott@desktop ~ $ sensors --version > > sensors version 3.4.0+git_83cafd29f28d463573750d897014ec7143217ae5 > > with libsensors version 3.4.0+git_83cafd29f28d463573750d897014ec7143217ae5 > > I'm using a fairly recent version of sbcl built from source that > (apparently) passed all of the tests after the build: > > > CL-USER> (lisp-implementation-version) > > "1.4.6.140-f8d5864d0" > > My version of cffi appears to be the latest: > > > CL-USER> (slot-value (asdf:find-system :cffi) 'asdf:version) > > "0.19.0" > > My system uses cffi-grovel and defines the following structs: > > > (cstruct sensors-bus-id "sensors_bus_id" > > (type "type" :type :short) > > (nr "nr" :type :short)) > > > > (cstruct sensors-chip-name "sensors_chip_name" > > (prefix "prefix" :type :string) > > (bus "bus" :type (:struct sensors-bus-id)) > > (address "addr" :type :int) > > (path "path" :type :string)) > > These are based upon the definitions in sensors/sensors.h: > https://github.com/groeck/lm-sensors/blob/master/lib/sensors.h > > After asdf loading the system, the following groveler definitions are > created (had to dig these out of the cached build files): > > (cffi:defcstruct (sensors-bus-id :size 4) > > (type :short :offset 0) > > (nr :short :offset 2)) > > (cl:defconstant size-of-sensors-bus-id (cffi:foreign-type-size > > '(:struct sensors-bus-id))) > > (cffi:defcstruct (sensors-chip-name :size 24) > > (prefix :string :offset 0) > > (bus (:struct sensors-bus-id) :offset 8) > > (address :int :offset 12) > > (path :string :offset 16)) > > (cl:defconstant size-of-sensors-chip-name (cffi:foreign-type-size > > '(:struct sensors-chip-name))) > All of the above appears to be correct, so I proceed to load the library: > > (define-foreign-library libsensors > > (:unix (:or "libsensors.so.4" "libsensors.so")) > > (t (:default "libsensors.so"))) > > (use-foreign-library libsensors) > No issues, so I define a c function from the c header file that parses a > sensor chip name-string into a struct: > > > (defcfun ("sensors_parse_chip_name" cffi-sensors-parse-chip-name) :int > > "Parse a chip name to the internal representation. Return 0 on > > success, <0 on error." > > (orig-name :string) > > (res (:pointer (:struct sensors-chip-name)))) > > Which is based upon the following header function declaration: > > > int sensors_parse_chip_name(const char *orig_name, sensors_chip_name > > *res); > > Then I implement a simple call to print out the parsed values (not > including the bus): > > > (defun test-sensors-parse-chip-name (string) > > (with-foreign-object (name '(:struct sensors-chip-name)) > > (unless (= 0 (cffi-sensors-parse-chip-name string name)) > > (error "Failed to parse: ~A" string)) > > (with-foreign-slots ((prefix address path) > > name > > (:struct sensors-chip-name)) > > (format t "~%Prefix: '~A'" prefix) > > (format t "~%Address: '~A'" address) > > (format t "~%Path: '~A'" path)))) > > The above when executed gives the following output before the error: > > > CL-LMSENSORS> (test-sensors-parse-chip-name "atk0110-acpi-0") > > > > Prefix: 'atk0110' > > Address: '0' > > And once it tries to access the path variable, it gives the following > error (sorry a lot rolls off the screen): > > > Unhandled memory fault at #xE71B7. > > [Condition of type SB-SYS:MEMORY-FAULT-ERROR] > > > > Restarts: > > 0: [RETRY] Retry SLIME REPL evaluation request. > > 1: [*ABORT] Return to SLIME's top level. > > 2: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING {1002207F93}>) > > > > Backtrace: > > 0: (CFFI::FOREIGN-STRING-LENGTH #.(SB-SYS:INT-SAP #X000E71B7) > > :ENCODING :UTF-8 :OFFSET 0) > > Locals: > > #:.DEFAULTING-TEMP. = :UTF-8 > > #:.DEFAULTING-TEMP.#1 = 0 > > #:N-SUPPLIED-0 = 1 > > POINTER = #.(SB-SYS:INT-SAP #X000E71B7) > > 1: (FOREIGN-STRING-TO-LISP #.(SB-SYS:INT-SAP #X000E71B7) :OFFSET 0 > > :COUNT NIL :MAX-CHARS 4611686018427387900 :ENCODING :UTF-8$ > > Locals: > > #:.DEFAULTING-TEMP. = 0 > > #:.DEFAULTING-TEMP.#1 = NIL > > #:.DEFAULTING-TEMP.#2 = 4611686018427387900 > > #:.DEFAULTING-TEMP.#3 = :UTF-8 > > ENCODING = :UTF-8 > > #:N-SUPPLIED-0 = 1 > > POINTER = #.(SB-SYS:INT-SAP #X000E71B7) > > 2: ((:METHOD TRANSLATE-FROM-FOREIGN (T CFFI::FOREIGN-STRING-TYPE)) > > #.(SB-SYS:INT-SAP #X000E71B7) #<CFFI::FOREIGN-STRING-TYPE $ > > 3: (TEST-SENSORS-PARSE-CHIP-NAME "atk0110-acpi-0") > My guess is I'm not defining the (:struct sensors-chip-name) correctly, > so that when sensors_parse_chip_name writes values into the struct, it > somehow overlaps into the path string. > > When looking at the source for sensors_parse_chip_name I've noticed that > it does not set or access the path value at all. So I decided to write > a small c program to test the native behavior: > > > elliott@desktop ~ $ cat test-sensors.c > > #include <stdio.h> > > #include <stdlib.h> > > #include "sensors/sensors.h" > > > > int main( ) { > > > > //sensors_init( NULL ); > > > > struct sensors_chip_name name; > > > > int return_value = sensors_parse_chip_name( "atk0110-acpi-0", &name); > > if ( return_value != 0 ) { > > printf( "Failed to get a good return value." ); > > exit( return_value ); > > } > > > > printf( "Printing the prefix: '%s'\n", name.prefix ); > > printf( "Address: '%i'\n", name.addr ); > > printf( "Printing path value: '%s'\n", name.path ); > > printf ("\n exiting..." ); > > > > exit( 0 ); > > } > > elliott@desktop ~ $ gcc test-sensors.c -l sensors -o test-sensors > > elliott@desktop ~ $ ./test-sensors > > Printing the prefix: 'atk0110' > > Address: '0' > > Printing path value: '' > > > > exiting... > No problems there, so I assume that the issue is all my lack of cffi-fu > training. Any pointers (yes, pun intended) would be appreciated... > sorry for such a long read, but I hope it helps to have the background. > At the very least it helped me to frame the issue in my mind by writing > this. > > Regards, > Elliott > >
