diff --git a/loadlib.c b/loadlib.c new file mode 100644 index 00000000..69b1339e --- /dev/null +++ b/loadlib.c @@ -0,0 +1,173 @@ +/* +** $Id$ +** Bare-bones dynamic library loader for Lua +** See Copyright Notice in lua.h +* +* This Lua library exports a single function, called loadlib, which is +* called from Lua as loadlib(lib,init), where lib is the full name of the +* library to be loaded (including the complete path) and init is the name +* of a function to be called after the library is loaded. Typically, this +* function will register other functions, thus making the complete library +* available to Lua. The init function is *not* automatically called by +* loadlib. Instead, loadlib returns the init function as a Lua function +* that the client can call when it thinks is appropriate. In the case of +* errors, loadlib returns nil and two strings describing the error. +* The first string is supplied by the operating system; it should be +* informative and useful for error messages. The second string is "open", +* "init", or "absent" to identify the error and is meant to be used for +* making decisions without having to look into the first string (whose +* format is system-dependent). +* +* This bare-bones loadlib function is supposed to be used as a foundation +* for more sophisticated dynamic library loaders, possibly still called +* loadlib and probably written in Lua, that will be smart enough to try to +* find the library in different directories and also perhaps guess the name +* of the init function. +* +* This module contains an implementation of loadlib for Unix systems that +* have dlfcn, an implementation for Windows, and a stub for other systems. +* See the list at the end of this file for some links to available +* implementations of dlfcn and interfaces to other native dynamic loaders +* on top of which loadlib could be implemented. +* +*/ + +#include "lua.h" +#include "lauxlib.h" +#include "lualib.h" + +#ifndef USE_LOADLIB +#define USE_LOADLIB 1 +#endif + +#ifndef USE_DLOPEN +#define USE_DLOPEN 0 +#endif + +#if USE_LOADLIB + +#if defined(linux) || defined(sun) || defined(sgi) || defined(BSD) || USE_DLOPEN +#define LOADLIB +/* +* This is an implementation of loadlib based on the dlfcn interface. +* The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +* NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +* as an emulation layer on top of native functions. +*/ + +#include + +static int loadlib(lua_State *L) +{ + const char *path=luaL_checkstring(L,1); + const char *init=luaL_checkstring(L,2); + void *lib=dlopen(path,RTLD_NOW); + if (lib!=NULL) + { + lua_CFunction f=(lua_CFunction) dlsym(lib,init); + if (f!=NULL) + { + lua_pushlightuserdata(L,lib); + lua_pushcclosure(L,f,1); + return 1; + } + } + lua_pushnil(L); + lua_pushstring(L,dlerror()); + lua_pushstring(L,(lib!=NULL) ? "init" : "open"); + if (lib!=NULL) dlclose(lib); + return 3; +} + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +#define LOADLIB +/* +* This is an implementation of loadlib for Windows using native functions. +*/ + +#include + +static void pusherror(lua_State *L) +{ + int error=GetLastError(); + char buffer[128]; + if (FormatMessage(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + 0, error, 0, buffer, sizeof(buffer), 0)) + lua_pushstring(L,buffer); + else + lua_pushfstring("system error %d\n",error); +} + +static int loadlib(lua_State *L) +{ + const char *path=luaL_checkstring(L,1); + const char *init=luaL_checkstring(L,2); + HINSTANCE lib=LoadLibrary(path); + if (lib!=NULL) + { + lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init); + if (f!=NULL) + { + lua_pushlightuserdata(L,lib); + lua_pushcclosure(L,f,1); + return 1; + } + } + lua_pushnil(L); + pusherror(L); + lua_pushstring(L,(lib!=NULL) ? "init" : "open"); + if (lib!=NULL) FreeLibrary(lib); + return 3; +} + +#else +/* +* write an implementation for your system here and send it to us, together +* with preprocessing symbols that identify your system. +*/ +#endif +#endif + +#ifndef LOADLIB +/* Fallback for other systems */ + +static int loadlib(lua_State *L) +{ + lua_pushnil(L); + lua_pushliteral(L,"`loadlib' not supported"); + lua_pushliteral(L,"absent"); + return 3; +} +#endif + +LUALIB_API int luaopen_loadlib (lua_State *L) +{ + lua_register(L,"loadlib",loadlib); + return 0; +} + +/* +* Here are some links por to available implementations of dlfcn and +* interfaces to other native dynamic loaders on top of which loadlib could +* be implemented. Please send contributions and corrections to us. +* +* AIX +* Starting with AIX 4.2, dlfcn is included in the base OS. +* There is also an emulation package available. +* http://www.faqs.org/faqs/aix-faq/part4/section-21.html +* +* HPUX +* HPUX 11 has dlfcn. For HPUX 10 use shl_*. +* http://www.geda.seul.org/mailinglist/geda-dev37/msg00094.html +* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html +* +* Macintosh, Windows +* http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html +* +* Mac OS X/Darwin +* http://www.opendarwin.org/projects/dlcompat/ +* +* GLIB has wrapper code for BeOS, OS2, Unix and Windows +* http://cvs.gnome.org/lxr/source/glib/gmodule/ +* +*/ diff --git a/lualib.h b/lualib.h index d393b66d..23e64fce 100644 --- a/lualib.h +++ b/lualib.h @@ -1,5 +1,5 @@ /* -** $Id: lualib.h,v 1.25 2002/07/09 18:49:13 roberto Exp roberto $ +** $Id: lualib.h,v 1.26 2003/03/11 12:24:34 roberto Exp roberto $ ** Lua standard libraries ** See Copyright Notice in lua.h */ @@ -36,6 +36,9 @@ LUALIB_API int luaopen_math (lua_State *L); LUALIB_API int luaopen_debug (lua_State *L); +LUALIB_API int luaopen_loadlib (lua_State *L); + + /* to help testing the libraries */ #ifndef lua_assert #define lua_assert(c) /* empty */