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 | * |