<html>
  <head>

    <meta http-equiv="content-type" content="text/html; charset=utf-8">
  </head>
  <body bgcolor="#FFFFFF" text="#000000">
    <p>Hello,</p>
    <p>If this is not the correct list to report a user error, I
      apologize and will happily redirect my question where ever
      suitable.</p>
    <p>I've been using cffi to make a trivial library to libsensors
      <a class="moz-txt-link-freetext" href="https://github.com/groeck/lm-sensors">https://github.com/groeck/lm-sensors</a> 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.<br>
    </p>
    <p>Here's my information:<br>
    </p>
    <p>Running a 64 bit linux install.  My local version of the
      libsensors library is as follows:</p>
    <p>
      <blockquote type="cite">elliott@desktop ~ $ file
        /usr/lib64/libsensors.so.4.4.0<br>
        /usr/lib64/libsensors.so.4.4.0: ELF 64-bit LSB shared object,
        x86-64, version 1 (SYSV), dynamically linked, stripped</blockquote>
      <blockquote type="cite">elliott@desktop ~ $ sensors --version<br>
        sensors version
        3.4.0+git_83cafd29f28d463573750d897014ec7143217ae5 with
        libsensors version
        3.4.0+git_83cafd29f28d463573750d897014ec7143217ae5</blockquote>
    </p>
    <p>I'm using a fairly recent version of sbcl built from source that
      (apparently) passed all of the tests after the build:<br>
    </p>
    <p> </p>
    <blockquote type="cite">CL-USER> (lisp-implementation-version)<br>
      "1.4.6.140-f8d5864d0"<br>
    </blockquote>
    <p>My version of cffi appears to be the latest:</p>
    <p>
      <blockquote type="cite">CL-USER> (slot-value (asdf:find-system
        :cffi) 'asdf:version)<br>
        "0.19.0"<br>
      </blockquote>
    </p>
    <p>My system uses cffi-grovel and defines the following structs:</p>
    <p>
      <blockquote type="cite">(cstruct sensors-bus-id "sensors_bus_id"<br>
                 (type "type" :type :short)<br>
                 (nr "nr" :type :short))<br>
                                                                                                                              
         <br>
        (cstruct sensors-chip-name "sensors_chip_name"<br>
                 (prefix "prefix" :type :string)<br>
                 (bus "bus" :type (:struct sensors-bus-id))<br>
                 (address "addr" :type :int)<br>
                 (path "path" :type :string))<br>
      </blockquote>
    </p>
    <p>These are based upon the definitions in sensors/sensors.h:
      <a class="moz-txt-link-freetext" href="https://github.com/groeck/lm-sensors/blob/master/lib/sensors.h">https://github.com/groeck/lm-sensors/blob/master/lib/sensors.h</a></p>
    After asdf loading the system, the following groveler definitions
    are created (had to dig these out of the cached build files):<br>
    <blockquote type="cite">(cffi:defcstruct (sensors-bus-id :size 4)<br>
        (type :short :offset 0)<br>
        (nr :short :offset 2))<br>
      (cl:defconstant size-of-sensors-bus-id (cffi:foreign-type-size
      '(:struct sensors-bus-id)))<br>
      (cffi:defcstruct (sensors-chip-name :size 24)<br>
        (prefix :string :offset 0)<br>
        (bus (:struct sensors-bus-id) :offset 8)<br>
        (address :int :offset 12)<br>
        (path :string :offset 16))<br>
      (cl:defconstant size-of-sensors-chip-name (cffi:foreign-type-size
      '(:struct sensors-chip-name)))</blockquote>
    All of the above appears to be correct, so I proceed to load the
    library:<br>
    <blockquote type="cite">(define-foreign-library libsensors<br>
        (:unix (:or "libsensors.so.4" "libsensors.so"))<br>
        (t (:default "libsensors.so")))<br>
      (use-foreign-library libsensors)<br>
    </blockquote>
    No issues, so I define a c function from the c header file that
    parses a sensor chip name-string into a struct:<br>
    <br>
    <blockquote type="cite">(defcfun ("sensors_parse_chip_name"
      cffi-sensors-parse-chip-name) :int<br>
        "Parse a chip name to the internal representation.  Return 0 on
      success, <0 on error."<br>
        (orig-name :string) <br>
        (res (:pointer (:struct sensors-chip-name))))</blockquote>
    <br>
    Which is based upon the following header function declaration:<br>
    <br>
    <blockquote type="cite">
      <meta http-equiv="content-type" content="text/html; charset=utf-8">
      <span class="pl-k">int</span> <span class="pl-smi">sensors_parse_chip_name</span>(<span
        class="pl-k">const</span> <span class="pl-k">char</span>
      *orig_name, sensors_chip_name *res);</blockquote>
    <br>
    Then I implement a simple call to print out the parsed values (not
    including the bus):<br>
    <br>
    <blockquote type="cite">(defun test-sensors-parse-chip-name
      (string)                            <br>
        (with-foreign-object (name '(:struct sensors-chip-name))<br>
          (unless (= 0 (cffi-sensors-parse-chip-name string name))<br>
            (error "Failed to parse: ~A" string))<br>
          (with-foreign-slots ((prefix address path)<br>
                               name<br>
                               (:struct sensors-chip-name))<br>
            (format t "~%Prefix: '~A'" prefix)<br>
            (format t "~%Address: '~A'" address)<br>
            (format t "~%Path: '~A'" path))))</blockquote>
    <br>
    The above when executed gives the following output before the error:<br>
    <br>
    <blockquote type="cite">CL-LMSENSORS>
      (test-sensors-parse-chip-name "atk0110-acpi-0")<br>
      <br>
      Prefix: 'atk0110'<br>
      Address: '0'</blockquote>
    <br>
    And once it tries to access the path variable, it gives the
    following error (sorry a lot rolls off the screen):<br>
    <br>
    <blockquote type="cite">Unhandled memory fault at #xE71B7.<br>
         [Condition of type SB-SYS:MEMORY-FAULT-ERROR]<br>
      <br>
      Restarts:<br>
       0: [RETRY] Retry SLIME REPL evaluation request.<br>
       1: [*ABORT] Return to SLIME's top level.<br>
       2: [ABORT] abort thread (#<THREAD "repl-thread" RUNNING
      {1002207F93}>) <br>
      <br>
      Backtrace:<br>
        0: (CFFI::FOREIGN-STRING-LENGTH #.(SB-SYS:INT-SAP #X000E71B7)
      :ENCODING :UTF-8 :OFFSET 0)<br>
            Locals:<br>
              #:.DEFAULTING-TEMP. = :UTF-8<br>
              #:.DEFAULTING-TEMP.#1 = 0<br>
              #:N-SUPPLIED-0 = 1<br>
              POINTER = #.(SB-SYS:INT-SAP #X000E71B7)<br>
        1: (FOREIGN-STRING-TO-LISP #.(SB-SYS:INT-SAP #X000E71B7) :OFFSET
      0 :COUNT NIL :MAX-CHARS 4611686018427387900 :ENCODING :UTF-8$<br>
            Locals: <br>
              #:.DEFAULTING-TEMP. = 0<br>
              #:.DEFAULTING-TEMP.#1 = NIL<br>
              #:.DEFAULTING-TEMP.#2 = 4611686018427387900<br>
              #:.DEFAULTING-TEMP.#3 = :UTF-8<br>
              ENCODING = :UTF-8<br>
              #:N-SUPPLIED-0 = 1<br>
              POINTER = #.(SB-SYS:INT-SAP #X000E71B7)<br>
        2: ((:METHOD TRANSLATE-FROM-FOREIGN (T
      CFFI::FOREIGN-STRING-TYPE)) #.(SB-SYS:INT-SAP #X000E71B7)
      #<CFFI::FOREIGN-STRING-TYPE $<br>
        3: (TEST-SENSORS-PARSE-CHIP-NAME "atk0110-acpi-0") </blockquote>
    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.  <br>
    <br>
    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:<br>
    <br>
    <blockquote type="cite">elliott@desktop ~ $ cat test-sensors.c<br>
      #include <stdio.h><br>
      #include <stdlib.h><br>
      #include "sensors/sensors.h"<br>
      <br>
      int main( ) {<br>
      <br>
        //sensors_init( NULL );<br>
      <br>
        struct sensors_chip_name name;<br>
      <br>
        int return_value = sensors_parse_chip_name( "atk0110-acpi-0",
      &name);<br>
        if ( return_value != 0 ) {<br>
          printf( "Failed to get a good return value." );<br>
          exit( return_value );<br>
        }<br>
      <br>
        printf( "Printing the prefix: '%s'\n", name.prefix );<br>
        printf( "Address: '%i'\n", name.addr );  <br>
        printf( "Printing path value: '%s'\n", name.path );<br>
        printf ("\n exiting..." );<br>
        <br>
        exit( 0 );<br>
      }         <br>
      elliott@desktop ~ $ gcc test-sensors.c -l sensors -o test-sensors<br>
      elliott@desktop ~ $ ./test-sensors <br>
      Printing the prefix: 'atk0110'<br>
      Address: '0'<br>
      Printing path value: ''<br>
      <br>
       exiting... <br>
    </blockquote>
    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.<br>
    <br>
    Regards,<br>
    Elliott<br>
    <br>
  </body>
</html>