Dear Gambit enthusiasts, I think I figured out how to use dlopen to run functions from Gambit that live in dynamically loaded libraries (plugins); my best to date is below. But I'm not quite happy with it--because it's kind of elaborate. That is, I couldn't figure out how to avoid some of the boiler plate below. Perhaps there is a shorter way? So my question for Gambit enthusiasts is: Is there a cleaner way to do this--to run functions from plugin libraries? i.e. without having to pre-declare call_plugin_print8 and call_print8. What if you wanted to make such a call after inspecting a new library at runtime? Many thanks! Gambit rocks! Thanks again for such a great system. - Jason ;;;;;;;;;;;;;;; file: libex.cpp ;;;;;;;;;;;; ; ; a simple library of one function for ; testing/development of plugin loading ; #include <stdio.h> extern "C" int print8() { printf("\n In print8() : returning 8\n"); return 8; } ;;;;;;;;;;;;;;; file: libex.h ;;;;;;;;;;;; #ifndef LIBEX_H #define LIBEX_H int print8(); #endif ;;;;;;;;;;;;;;; file: dlopen.scm ;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; dlopen.scm : plugins in Gambit ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; compile and link with: ; ; gsc -link dlopen.scm ; gcc -I/usr/local/Gambit-C/include -L/usr/local/Gambit-C/lib dlopen.c dlopen_.c -lgambc -lm -lutil -ldl -o dlopen (c-declare #<<c-declare-end #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> #include "libex.h" /* simple wrapper to do runtime plugin function calls (call into .so library) */ int call_plugin_print8(void* handle) { char *error; int (*my_func)(); // my_func = (int (*)()) dlsym(handle,"print8"); *(void **) (&my_func) = dlsym(handle, "print8"); if ((error = dlerror()) != NULL) { fprintf(stderr, "%s\n", error); exit(EXIT_FAILURE); } return (*my_func)(); } c-declare-end ) ; from dlfcn.h ; see man dlopen ; ; void * dlopen(const char *filename, int flag); ; char * dlerror(void); ; void * dlsym(void *handle, const char *symbol); ; int dlclose(void *handle); ; ; translated into Gambit-C FFI: ; (define dlopen (c-lambda (nonnull-char-string int32) (pointer void) "dlopen")) (define dlerror (c-lambda () char-string "dlerror")) (define dlsym (c-lambda ((pointer void) nonnull-char-string) (pointer void) "dlsym")) (define dlclose (c-lambda ((pointer void)) int32 "dlclose")) ;; hmm is there a defconstant in scheme that we could use for these C header constants? ;; for now generate a function of the same name to get us the constant int value we need. (define RTLD_LAZY (c-lambda () int32 "___result = RTLD_LAZY;")) ; declare the type of the foreign function (define call_print8 (c-lambda ((pointer void)) int32 "call_plugin_print8")) (let* ((h (dlopen "/home/jaten/dj/gamb/libex.so" (RTLD_LAZY))) (res (dlsym h "print8"))) (if (null? res) (error "could not locate symbol 'print8' in the plugin library!")) (pretty-print (list "calling print8() gives: " (call_print8 h))) (pretty-print res) (pretty-print h) (pretty-print (list "The value of the constant RTLD_LAZY is: " (RTLD_LAZY)))) ;; output: ;;; $ ./dlopen ; ; In print8() : returning 8 ;8 ;#<void* #2 0x7fdd20c1868c> ;#<void* #3 0x22cd7b0> ;("The value of the constant RTLD_LAZY is: " 1) ;;;;;;;;;;;;;;; file: Makefile ;;;;;;;;;;;; all: gsc -link dlopen.scm gcc -I/usr/local/Gambit-C/include -L/usr/local/Gambit-C/lib dlopen.c dlopen_.c -lgambc -lm -lutil -ldl -o dlopen g++ -c libex.cpp -fpic -o libex.o g++ -shared libex.o -o libex.so @echo "testing ./dlopen" ./dlopen clean: rm -f dlopen dlopen_.c dlopen.c dlopen.o1 dlopen.o2 *~ *.o *.so