[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