diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-10-18 15:07:31 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2004-10-18 15:07:31 -0300 |
| commit | 3e1a1f28362d53104a6ef09fadd902e91657f8ce (patch) | |
| tree | a81941b3417bc771e0616f43e5823a68b785d966 | |
| parent | b32e9a46d24f949803bcfd11d637436fb4ccb076 (diff) | |
| download | lua-3e1a1f28362d53104a6ef09fadd902e91657f8ce.tar.gz lua-3e1a1f28362d53104a6ef09fadd902e91657f8ce.tar.bz2 lua-3e1a1f28362d53104a6ef09fadd902e91657f8ce.zip | |
better configuration for loadlib + tested Mac OS X version
| -rw-r--r-- | loadlib.c | 118 |
1 files changed, 66 insertions, 52 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: loadlib.c,v 1.6 2004/04/30 20:13:38 roberto Exp roberto $ | 2 | ** $Id: loadlib.c,v 1.7 2004/10/07 17:27:20 roberto Exp roberto $ |
| 3 | ** Dynamic library loader for Lua | 3 | ** Dynamic library loader for Lua |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | * | 5 | * |
| @@ -33,11 +33,10 @@ | |||
| 33 | #include "lualib.h" | 33 | #include "lualib.h" |
| 34 | 34 | ||
| 35 | 35 | ||
| 36 | #undef LOADLIB | 36 | static void registerlib (lua_State *L, const void *lib); |
| 37 | 37 | ||
| 38 | 38 | ||
| 39 | #ifdef USE_DLOPEN | 39 | #if defined(USE_DLOPEN) |
| 40 | #define LOADLIB | ||
| 41 | /* | 40 | /* |
| 42 | * This is an implementation of loadlib based on the dlfcn interface. | 41 | * This is an implementation of loadlib based on the dlfcn interface. |
| 43 | * The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, | 42 | * The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, |
| @@ -47,6 +46,8 @@ | |||
| 47 | 46 | ||
| 48 | #include <dlfcn.h> | 47 | #include <dlfcn.h> |
| 49 | 48 | ||
| 49 | #define freelib dlclose | ||
| 50 | |||
| 50 | static int loadlib(lua_State *L) | 51 | static int loadlib(lua_State *L) |
| 51 | { | 52 | { |
| 52 | const char *path=luaL_checkstring(L,1); | 53 | const char *path=luaL_checkstring(L,1); |
| @@ -57,8 +58,8 @@ static int loadlib(lua_State *L) | |||
| 57 | lua_CFunction f=(lua_CFunction) dlsym(lib,init); | 58 | lua_CFunction f=(lua_CFunction) dlsym(lib,init); |
| 58 | if (f!=NULL) | 59 | if (f!=NULL) |
| 59 | { | 60 | { |
| 60 | lua_pushlightuserdata(L,lib); | 61 | registerlib(L, lib); |
| 61 | lua_pushcclosure(L,f,1); | 62 | lua_pushcfunction(L,f); |
| 62 | return 1; | 63 | return 1; |
| 63 | } | 64 | } |
| 64 | } | 65 | } |
| @@ -70,30 +71,17 @@ static int loadlib(lua_State *L) | |||
| 70 | return 3; | 71 | return 3; |
| 71 | } | 72 | } |
| 72 | 73 | ||
| 73 | #endif | ||
| 74 | |||
| 75 | |||
| 76 | |||
| 77 | /* | ||
| 78 | ** In Windows, default is to use dll; otherwise, default is not to use dll | ||
| 79 | */ | ||
| 80 | #ifndef USE_DLL | ||
| 81 | #ifdef _WIN32 | ||
| 82 | #define USE_DLL 1 | ||
| 83 | #else | ||
| 84 | #define USE_DLL 0 | ||
| 85 | #endif | ||
| 86 | #endif | ||
| 87 | 74 | ||
| 88 | 75 | ||
| 89 | #if USE_DLL | 76 | #elif defined(USE_DLL) |
| 90 | #define LOADLIB | ||
| 91 | /* | 77 | /* |
| 92 | * This is an implementation of loadlib for Windows using native functions. | 78 | * This is an implementation of loadlib for Windows using native functions. |
| 93 | */ | 79 | */ |
| 94 | 80 | ||
| 95 | #include <windows.h> | 81 | #include <windows.h> |
| 96 | 82 | ||
| 83 | #define freelib(lib) FreeLibrary((HINSTANCE)lib) | ||
| 84 | |||
| 97 | static void pusherror(lua_State *L) | 85 | static void pusherror(lua_State *L) |
| 98 | { | 86 | { |
| 99 | int error=GetLastError(); | 87 | int error=GetLastError(); |
| @@ -115,8 +103,8 @@ static int loadlib(lua_State *L) | |||
| 115 | lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init); | 103 | lua_CFunction f=(lua_CFunction) GetProcAddress(lib,init); |
| 116 | if (f!=NULL) | 104 | if (f!=NULL) |
| 117 | { | 105 | { |
| 118 | lua_pushlightuserdata(L,lib); | 106 | registerlib(L, lib); |
| 119 | lua_pushcclosure(L,f,1); | 107 | lua_pushcfunction(L,f); |
| 120 | return 1; | 108 | return 1; |
| 121 | } | 109 | } |
| 122 | } | 110 | } |
| @@ -127,19 +115,28 @@ static int loadlib(lua_State *L) | |||
| 127 | return 3; | 115 | return 3; |
| 128 | } | 116 | } |
| 129 | 117 | ||
| 130 | #endif | 118 | |
| 131 | 119 | ||
| 132 | /* Native Mac OS X / Darwin Implementation */ | 120 | /* Native Mac OS X / Darwin Implementation */ |
| 133 | #ifdef USE_DYLD | 121 | #elif defined(USE_DYLD) |
| 134 | #define LOADLIB | ||
| 135 | 122 | ||
| 136 | #include <mach-o/dyld.h> | 123 | #include <mach-o/dyld.h> |
| 137 | 124 | ||
| 125 | |||
| 126 | /* Mach cannot unload images (?) */ | ||
| 127 | #define freelib(lib) ((void)lib) | ||
| 128 | |||
| 129 | static void pusherror (lua_State *L) | ||
| 130 | { | ||
| 131 | const char *err_str; | ||
| 132 | const char *err_file; | ||
| 133 | NSLinkEditErrors err; | ||
| 134 | int err_num; | ||
| 135 | NSLinkEditError(&err, &err_num, &err_file, &err_str); | ||
| 136 | lua_pushstring(L, err_str); | ||
| 137 | } | ||
| 138 | |||
| 138 | static int loadlib (lua_State *L) { | 139 | static int loadlib (lua_State *L) { |
| 139 | const char * err_str; | ||
| 140 | const char * err_file; | ||
| 141 | NSLinkEditErrors err; | ||
| 142 | int err_num; | ||
| 143 | const char *path=luaL_checkstring(L,1); | 140 | const char *path=luaL_checkstring(L,1); |
| 144 | const char *init=luaL_checkstring(L,2); | 141 | const char *init=luaL_checkstring(L,2); |
| 145 | const struct mach_header *lib; | 142 | const struct mach_header *lib; |
| @@ -150,7 +147,6 @@ static int loadlib (lua_State *L) { | |||
| 150 | lua_pushstring(L,"absent"); | 147 | lua_pushstring(L,"absent"); |
| 151 | return 3; | 148 | return 3; |
| 152 | } | 149 | } |
| 153 | |||
| 154 | lib = NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR); | 150 | lib = NSAddImage(path, NSADDIMAGE_OPTION_RETURN_ON_ERROR); |
| 155 | if(lib != NULL) { | 151 | if(lib != NULL) { |
| 156 | NSSymbol init_sym = NSLookupSymbolInImage(lib, init, | 152 | NSSymbol init_sym = NSLookupSymbolInImage(lib, init, |
| @@ -158,49 +154,70 @@ static int loadlib (lua_State *L) { | |||
| 158 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); | 154 | NSLOOKUPSYMBOLINIMAGE_OPTION_RETURN_ON_ERROR); |
| 159 | if(init_sym != NULL) { | 155 | if(init_sym != NULL) { |
| 160 | lua_CFunction f = (lua_CFunction)NSAddressOfSymbol(init_sym); | 156 | lua_CFunction f = (lua_CFunction)NSAddressOfSymbol(init_sym); |
| 161 | lua_pushlightuserdata(L,(void *)lib); | 157 | registerlib(L, lib); |
| 162 | lua_pushcclosure(L,f,1); | 158 | lua_pushcfunction(L,f); |
| 163 | return 1; | 159 | return 1; |
| 164 | } | 160 | } |
| 165 | } | 161 | } |
| 166 | /* else an error ocurred */ | 162 | /* else an error ocurred */ |
| 167 | NSLinkEditError(&err, &err_num, &err_file, &err_str); | ||
| 168 | lua_pushnil(L); | 163 | lua_pushnil(L); |
| 169 | lua_pushstring(L, err_str); | 164 | pusherror(L); |
| 170 | lua_pushstring(L, (lib != NULL) ? "init" : "open"); | 165 | lua_pushstring(L, (lib != NULL) ? "init" : "open"); |
| 171 | /* Can't unload image */ | 166 | /* Can't unload image */ |
| 172 | return 3; | 167 | return 3; |
| 173 | } | 168 | } |
| 174 | 169 | ||
| 175 | #endif | ||
| 176 | |||
| 177 | 170 | ||
| 178 | 171 | ||
| 179 | #ifndef LOADLIB | 172 | #else |
| 180 | /* Fallback for other systems */ | 173 | /* Fallback for other systems */ |
| 181 | 174 | ||
| 182 | /* | ||
| 183 | ** Those systems support dlopen, so they should have defined USE_DLOPEN. | ||
| 184 | ** The default (no)implementation gives them a special error message. | ||
| 185 | */ | ||
| 186 | #if defined(linux) || defined(sun) || defined(sgi) || defined(BSD) || defined(_WIN32) | ||
| 187 | #define LOADLIB "`loadlib' not installed (check your Lua configuration)" | ||
| 188 | #else | ||
| 189 | #define LOADLIB "`loadlib' not supported" | ||
| 190 | #endif | ||
| 191 | 175 | ||
| 176 | #define freelib(lib) ((void)lib) | ||
| 192 | 177 | ||
| 193 | static int loadlib(lua_State *L) | 178 | static int loadlib(lua_State *L) |
| 194 | { | 179 | { |
| 180 | registerlib(L, NULL); /* to avoid warnings */ | ||
| 195 | lua_pushnil(L); | 181 | lua_pushnil(L); |
| 196 | lua_pushliteral(L,LOADLIB); | 182 | lua_pushliteral(L,"`loadlib' not supported"); |
| 197 | lua_pushliteral(L,"absent"); | 183 | lua_pushliteral(L,"absent"); |
| 198 | return 3; | 184 | return 3; |
| 199 | } | 185 | } |
| 186 | |||
| 200 | #endif | 187 | #endif |
| 201 | 188 | ||
| 189 | |||
| 190 | /* | ||
| 191 | ** common code for all implementations: put a library into the registry | ||
| 192 | ** so that, when Lua closes its state, the library's __gc metamethod | ||
| 193 | ** will be called to unload the library. | ||
| 194 | */ | ||
| 195 | static void registerlib (lua_State *L, const void *lib) | ||
| 196 | { | ||
| 197 | const void **plib = (const void **)lua_newuserdata(L, sizeof(const void *)); | ||
| 198 | *plib = lib; | ||
| 199 | luaL_getmetatable(L, "_LOADLIB"); | ||
| 200 | lua_setmetatable(L, -2); | ||
| 201 | lua_pushboolean(L, 1); | ||
| 202 | lua_settable(L, LUA_REGISTRYINDEX); /* registry[lib] = true */ | ||
| 203 | } | ||
| 204 | |||
| 205 | /* | ||
| 206 | ** __gc tag method: calls library's `freelib' function with the lib | ||
| 207 | ** handle | ||
| 208 | */ | ||
| 209 | static int gctm (lua_State *L) | ||
| 210 | { | ||
| 211 | void *lib = *(void **)luaL_checkudata(L, 1, "_LOADLIB"); | ||
| 212 | freelib(lib); | ||
| 213 | return 0; | ||
| 214 | } | ||
| 215 | |||
| 202 | LUALIB_API int luaopen_loadlib (lua_State *L) | 216 | LUALIB_API int luaopen_loadlib (lua_State *L) |
| 203 | { | 217 | { |
| 218 | luaL_newmetatable(L, "_LOADLIB"); | ||
| 219 | lua_pushcfunction(L, gctm); | ||
| 220 | lua_setfield(L, -2, "__gc"); | ||
| 204 | lua_register(L,"loadlib",loadlib); | 221 | lua_register(L,"loadlib",loadlib); |
| 205 | return 0; | 222 | return 0; |
| 206 | } | 223 | } |
| @@ -223,9 +240,6 @@ LUALIB_API int luaopen_loadlib (lua_State *L) | |||
| 223 | * Macintosh, Windows | 240 | * Macintosh, Windows |
| 224 | * http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html | 241 | * http://www.stat.umn.edu/~luke/xls/projects/dlbasics/dlbasics.html |
| 225 | * | 242 | * |
| 226 | * Mac OS X/Darwin | ||
| 227 | * http://www.opendarwin.org/projects/dlcompat/ | ||
| 228 | * | ||
| 229 | * GLIB has wrapper code for BeOS, OS2, Unix and Windows | 243 | * GLIB has wrapper code for BeOS, OS2, Unix and Windows |
| 230 | * http://cvs.gnome.org/lxr/source/glib/gmodule/ | 244 | * http://cvs.gnome.org/lxr/source/glib/gmodule/ |
| 231 | * | 245 | * |
