* mzscheme code can now dynamically load libraries, that are needed

at runtime. This allows for code to be generated at some site, and
  distributed without the need for SWIG.

  The distribution needs only the header filesfor which the code has been
   generated. Linking is done at runtime, by loading the dynamic libraries.

   Functions are resolved when needed.

   Though somewhat inefficient, it provides for a way to distribute code
   or binaries that are independent of the version of the installed libraries,

   which comes in especially handy for e.g. binding against Gtk.


git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk/SWIG@9211 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Hans Oesterholt-Dijkema 2006-07-09 17:10:05 +00:00
commit b593492d03
3 changed files with 260 additions and 4 deletions

11
.project Normal file
View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>SWIG</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
</buildSpec>
<natures>
</natures>
</projectDescription>

View file

@ -252,6 +252,199 @@ SWIG_MzScheme_new_scheme_struct (Scheme_Env* env, const char* basename,
return new_type;
}
/*** DLOPEN PATCH ******************************************************
* Contributed by Hans Oesterholt-Dijkema (jan. 2006)
***********************************************************************/
#if defined(_WIN32) || defined(__WIN32__)
#define __OS_WIN32
#endif
#ifdef __OS_WIN32
#include <windows.h>
#else
#include <dlfcn.h>
#endif
static char **mz_dlopen_libraries=NULL;
static void **mz_libraries=NULL;
static char **mz_dynload_libpaths=NULL;
static void mz_set_dlopen_libraries(const char *_libs)
{
int i,k,n;
int mz_dynload_debug=(1==0);
char *extra_paths[1000];
char *EP;
{
char *dbg=getenv("MZ_DYNLOAD_DEBUG");
if (dbg!=NULL) {
mz_dynload_debug=atoi(dbg);
}
}
{
char *ep=getenv("MZ_DYNLOAD_LIBPATH");
int i,k,j;
k=0;
if (ep!=NULL) {
EP=strdup(ep);
for(i=0,j=0;EP[i]!='\0';i++) {
if (EP[i]==':') {
EP[i]='\0';
extra_paths[k++]=&EP[j];
j=i+1;
}
}
if (j!=i) {
extra_paths[k++]=&EP[j];
}
}
else {
EP=strdup("");
}
extra_paths[k]=NULL;
k+=1;
if (mz_dynload_debug) {
fprintf(stderr,"SWIG:mzscheme:MZ_DYNLOAD_LIBPATH=%s\n",(ep==NULL) ? "(null)" : ep);
fprintf(stderr,"SWIG:mzscheme:extra_paths[%d]\n",k-1);
for(i=0;i<k-1;i++) {
fprintf(stderr,"SWIG:mzscheme:extra_paths[%d]=%s\n",i,extra_paths[i]);
}
}
mz_dynload_libpaths=(char **) malloc(sizeof(char *)*k);
for(i=0;i<k;i++) {
if (extra_paths[i]!=NULL) {
mz_dynload_libpaths[i]=strdup(extra_paths[i]);
}
else {
mz_dynload_libpaths[i]=NULL;
}
}
if (mz_dynload_debug) {
int i;
for(i=0;extra_paths[i]!=NULL;i++) {
fprintf(stderr,"SWIG:mzscheme:%s\n",extra_paths[i]);
}
}
}
{
#ifdef MZ_DYNLOAD_LIBS
char *libs=(char *) malloc((strlen(MZ_DYNLOAD_LIBS)+1)*sizeof(char));
strcpy(libs,MZ_DYNLOAD_LIBS);
#else
char *libs=(char *) malloc((strlen(_libs)+1)*sizeof(char));
strcpy(libs,_libs);
#endif
for(i=0,n=strlen(libs),k=0;i<n;i++) {
if (libs[i]==',') { k+=1; }
}
k+=1;
mz_dlopen_libraries=(char **) malloc(sizeof(char *)*(k+1));
mz_dlopen_libraries[0]=libs;
for(i=0,k=1,n=strlen(libs);i<n;i++) {
if (libs[i]==',') {
libs[i]='\0';
mz_dlopen_libraries[k++]=&libs[i+1];
i+=1;
}
}
if (mz_dynload_debug) {
fprintf(stderr,"k=%d\n",k);
}
mz_dlopen_libraries[k]=NULL;
free(EP);
}
}
static void *mz_load_function(char *function)
{
int mz_dynload_debug=(1==0);
{
char *dbg=getenv("MZ_DYNLOAD_DEBUG");
if (dbg!=NULL) {
mz_dynload_debug=atoi(dbg);
}
}
if (mz_dlopen_libraries==NULL) {
return NULL;
}
else {
if (mz_libraries==NULL) {
int i,n;
for(n=0;mz_dlopen_libraries[n]!=NULL;n++);
if (mz_dynload_debug) {
fprintf(stderr,"SWIG:mzscheme:n=%d\n",n);
}
mz_libraries=(void **) malloc(sizeof(void*)*n);
for(i=0;i<n;i++) {
if (mz_dynload_debug) {
fprintf(stderr,"SWIG:mzscheme:loading %s\n",mz_dlopen_libraries[i]);
}
#ifdef __OS_WIN32
mz_libraries[i]=(void *) LoadLibrary(mz_dlopen_libraries[i]);
#else
mz_libraries[i]=(void *) dlopen(mz_dlopen_libraries[i],RTLD_LAZY);
#endif
if (mz_libraries[i]==NULL) {
int k;
char *libp;
for(k=0;mz_dynload_libpaths[k]!=NULL && mz_libraries[i]==NULL;k++) {
int L=strlen(mz_dynload_libpaths[k])+strlen("\\")+strlen(mz_dlopen_libraries[i])+1;
libp=(char *) malloc(L*sizeof(char));
sprintf(libp,"%s\\%s",mz_dynload_libpaths[k],mz_dlopen_libraries[i]);
#ifdef __OS_WIN32
mz_libraries[i]=(void *) LoadLibrary(libp);
#else
mz_libraries[i]=(void *) dlopen(libp,RTLD_LAZY);
#endif
if (mz_dynload_debug) {
fprintf(stderr,"SWIG:mzscheme:trying %s --> %p\n",libp,mz_libraries[i]);
}
free(libp);
}
}
}
}
{
int i;
void *func=NULL;
for(i=0;mz_dlopen_libraries[i]!=NULL && func==NULL;i++) {
if (mz_libraries[i]!=NULL) {
#ifdef __OS_WIN32
func=GetProcAddress(mz_libraries[i],function);
#else
func=dlsym(mz_libraries[i],function);
#endif
}
if (mz_dynload_debug) {
fprintf(stderr,
"SWIG:mzscheme:library:%s;dlopen=%p,function=%s,func=%p\n",
mz_dlopen_libraries[i],mz_libraries[i],function,func
);
}
}
return func;
}
}
}
/*** DLOPEN PATCH ******************************************************
* Contributed by Hans Oesterholt-Dijkema (jan. 2006)
***********************************************************************/
/* The interpreter will store a pointer to this structure in a global
variable called swig-runtime-data-type-pointer. The instance of this
struct is only used if no other module has yet been loaded */
@ -311,3 +504,4 @@ SWIG_MzScheme_SetModule(Scheme_Env *env, swig_module_info *module) {
#ifdef __cplusplus
}
#endif

View file

@ -15,10 +15,13 @@ char cvsroot_mzscheme_cxx[] = "$Header$";
static const char *usage = (char*)"\
Mzscheme Options (available with -mzscheme)\n\
-prefix <name> - Set a prefix <name> to be prepended to all names\n\
-declaremodule - Create extension that declares a module\n\
-noinit - Do not emit scheme_initialize, scheme_reload,\n\
scheme_module_name functions\n";
-prefix <name> - Set a prefix <name> to be prepended to all names\n\
-declaremodule - Create extension that declares a module\n\
-noinit - Do not emit scheme_initialize, scheme_reload,\n\
scheme_module_name functions\n\
-dynamic-load <library>,[library,...] - Do not link with these libraries, dynamic load\n\
them\n\
";
static String *fieldnames_tab = 0;
static String *convert_tab = 0;
@ -29,6 +32,9 @@ static String *mangled_struct_name = 0;
static char *prefix=0;
static bool declaremodule = false;
static bool noinit = false;
//DLOPEN PATCH
static char *load_libraries = NULL;
//DLOPEN PATCH
static String *module=0;
static char *mzscheme_path=(char*)"mzscheme";
static String *init_func_def = 0;
@ -79,6 +85,14 @@ public:
noinit = true;
Swig_mark_arg (i);
}
// DLOPEN PATCH
else if (strcmp(argv[i],"-dynamic-load") == 0) {
load_libraries=new char[strlen(argv[i+1])+2];
strcpy(load_libraries,argv[i+1]);
Swig_mark_arg(i++);
Swig_mark_arg(i);
}
// DLOPEN PATCH
}
}
@ -153,6 +167,13 @@ public:
}
Printf (f_init, "\treturn scheme_void;\n}\n");
Printf(f_init, "Scheme_Object *scheme_initialize(Scheme_Env *env) {\n");
// DLOPEN PATCH
if (load_libraries) {
Printf(f_init,"mz_set_dlopen_libraries(\"%s\");\n",load_libraries);
}
// DLOPEN PATCH
Printf(f_init, "\treturn scheme_reload(env);\n");
Printf (f_init, "}\n");
@ -217,6 +238,15 @@ public:
int numreq;
String *overname = 0;
// PATCH DLOPEN
if (load_libraries) {
ParmList *parms=Getattr(n,"parms");
SwigType *type=Getattr(n,"type");
String *name=NewString("caller");
Setattr(n,"wrap:action", Swig_cresult(type,"result", Swig_cfunction_call(name,parms)));
}
// PATCH DLOPEN
// Make a wrapper name for this
String *wname = Swig_name_wrapper(iname);
if (Getattr(n,"sym:overloaded")) {
@ -255,11 +285,32 @@ public:
numargs = emit_num_arguments(l);
numreq = emit_num_required(l);
// DLOPEN PATCH
/* Add the holder for the pointer to the function to be opened */
if (load_libraries) {
Wrapper_add_local(f, "_function_loaded","static int _function_loaded=(1==0)");
Wrapper_add_local(f, "_the_function", "static void *_the_function=NULL");
{
String *parms=ParmList_protostr(l);
String *func=NewStringf("(*caller)(%s)",parms);
Wrapper_add_local(f,"caller",SwigType_lstr(d,func)); /*"(*caller)()"));*/
}
}
// DLOPEN PATCH
// adds local variables
Wrapper_add_local(f, "lenv", "int lenv = 1");
Wrapper_add_local(f, "values", "Scheme_Object *values[MAXVALUES]");
// DLOPEN PATCH
if (load_libraries) {
Printf(f->code,"if (!_function_loaded) { _the_function=mz_load_function(\"%s\");_function_loaded=(1==1); }\n",iname);
Printf(f->code,"if (!_the_function) { scheme_signal_error(\"Cannot load C function '%s'\"); }\n",iname);
Printf(f->code,"caller=_the_function;\n");
}
// DLOPEN PATCH
// Now write code to extract the parameters (this is super ugly)
for (i = 0, p = l; i < numargs; i++) {