Dear Gambit enthusiasts,<br><br>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.<br><br>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?<br>
<br>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?<br>
<br>Many thanks!  Gambit rocks!  Thanks again for such a great system.<br><br>- Jason<br><br><span style="font-family: courier new,monospace;">;;;;;;;;;;;;;;;  file: libex.cpp  ;;;;;;;;;;;;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;                 a simple library of one function for </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;                 testing/development of plugin loading  </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#include <stdio.h></span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">extern "C" int print8() {</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">  printf("\n In print8() : returning 8\n"); </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">  return 8; </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">}</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;;;;;;;;;;;;;;;  file: libex.h   ;;;;;;;;;;;;</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">#ifndef LIBEX_H</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#define LIBEX_H</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">int print8();</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">#endif</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;;;;;;;;;;;;;;;  file:  dlopen.scm   ;;;;;;;;;;;;</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;;  dlopen.scm : plugins in Gambit</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">; compile and link with:</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">; gsc -link dlopen.scm</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">; gcc -I/usr/local/Gambit-C/include -L/usr/local/Gambit-C/lib  dlopen.c  dlopen_.c  -lgambc -lm -lutil -ldl -o dlopen</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">(c-declare #<<c-declare-end</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">       #include <stdio.h></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">       #include <stdlib.h></span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">       #include <dlfcn.h></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">       #include "libex.h"</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">       /* simple wrapper to do runtime plugin function calls (call into .so library) */</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">       int call_plugin_print8(void* handle) {</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         char *error;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">         int (*my_func)();</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         // my_func               = (int (*)()) dlsym(handle,"print8");</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">         *(void **) (&my_func) = dlsym(handle, "print8");</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">     if ((error = dlerror()) != NULL)  </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">     {</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">         fprintf(stderr, "%s\n", error);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">         exit(EXIT_FAILURE);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">     }</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">     </span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">     return (*my_func)();</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">       }</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">c-declare-end</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">)</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;  from dlfcn.h ; see man dlopen</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;       void * dlopen(const char *filename, int flag);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;       char * dlerror(void);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;       void * dlsym(void *handle, const char *symbol);</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;       int    dlclose(void *handle);</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">; translated into Gambit-C FFI:</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">(define dlopen  (c-lambda (nonnull-char-string int32) (pointer void) "dlopen"))</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">(define dlerror (c-lambda () char-string "dlerror"))</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">(define dlsym   (c-lambda ((pointer void) nonnull-char-string) (pointer void) "dlsym"))</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">(define dlclose (c-lambda ((pointer void)) int32 "dlclose"))</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;; hmm is there a defconstant in scheme that we could use for these C header constants?</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;; for now generate a function of the same name to get us the constant int value we need.</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">(define RTLD_LAZY (c-lambda () int32 "___result = RTLD_LAZY;"))</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">; declare the type of the foreign function</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">(define call_print8 (c-lambda ((pointer void)) int32 "call_plugin_print8"))</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">(let* ((h  (dlopen "/home/jaten/dj/gamb/libex.so" (RTLD_LAZY)))</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">       (res (dlsym h "print8")))</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">       (if (null? res)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">     (error "could not locate symbol 'print8' in the plugin library!"))</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">     </span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">       (pretty-print (list "calling print8() gives: " (call_print8 h)))</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">       (pretty-print res)      </span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">       (pretty-print h)</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">       (pretty-print (list "The value of the constant RTLD_LAZY is: " (RTLD_LAZY))))</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;; output:</span><br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;;; $ ./dlopen</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">; In print8() : returning 8</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;8</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;#<void* #2 0x7fdd20c1868c></span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">;#<void* #3 0x22cd7b0></span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;("The value of the constant RTLD_LAZY is: " 1)</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">;;;;;;;;;;;;;;;  file: Makefile   ;;;;;;;;;;;;</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">all:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    gsc -link dlopen.scm</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    gcc -I/usr/local/Gambit-C/include -L/usr/local/Gambit-C/lib  dlopen.c  dlopen_.c  -lgambc -lm -lutil -ldl -o dlopen</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    g++ -c libex.cpp      -fpic -o libex.o</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    g++ -shared libex.o -o libex.so</span><br style="font-family: courier new,monospace;">
<span style="font-family: courier new,monospace;">    @echo "testing ./dlopen"</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    ./dlopen</span><br style="font-family: courier new,monospace;">
<br style="font-family: courier new,monospace;"><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">clean:</span><br style="font-family: courier new,monospace;"><span style="font-family: courier new,monospace;">    rm -f dlopen dlopen_.c dlopen.c dlopen.o1 dlopen.o2 *~ *.o *.so</span><br style="font-family: courier new,monospace;">
<br>