raspberry-piracketffiwiringpi

FFI with dependencies in Racket?


I developed a very simple FFI for the Wiring PI library, to be able to control a Raspberry Pi using Racket.

This worked well, but only covers the base functionality. I wanted to extend this to also use the lcd.h from the libwiringPiDev.so, so that I could create an FFI to control an LCD.

Normally, when you compile a C file that uses the LCD, you tag both the standard library and the development library when compiling:

-lwiringPi -lwiringPiDev

In my LCD FFI I did the following:

(define-ffi-definer define-lcd
  (ffi-lib "usr/lib/libwiringPiDev.so"))

However, when I try to require that racket file, I run into:

; ffi-lib: couldn't open "/usr/lib/libwiringPiDev.so"
;   (/usr/lib/libwiringPiDev.so: undefined symbol: digitalRead) [,bt for
;   context]

The digitalRead function exists in the base library but not in the dev library...how do I do a "FFI with dependencies" so that Racket can properly manage both libraries to be able to find the necessary symbols?


Solution

  • Try loading libwiringPi.so first in global mode, then load libwiringPiDev.so:

    (define-ffi-definer define-lcd
      (ffi-lib "/usr/lib/libwiringPi.so" #:global? #t))
    (define-ffi-definer define-lcd-dev
      (ffi-lib "/usr/lib/libwiringPiDev.so"))
    

    The #:global? #t argument corresponds to setting the RTLD_GLOBAL flag in the call to dlopen, and the man page for dlopen (on my Linux system) says

    RTLD_GLOBAL
    The symbols defined by this shared object will be made available for symbol resolution of subsequently loaded shared objects.