[gambit-list] dlopen -- is there a simpler way?

Jason E. Aten j.e.aten at gmail.com
Wed Apr 6 03:31:45 EDT 2011


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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.iro.umontreal.ca/pipermail/gambit-list/attachments/20110406/dffadd6e/attachment.htm>


More information about the Gambit-list mailing list