diff --git a/CHANGES.current b/CHANGES.current index 2b57da736..078600d4c 100644 --- a/CHANGES.current +++ b/CHANGES.current @@ -1,6 +1,10 @@ Version 1.3.32 (in progress) ============================ +07/10/2007: mgossage + [lua] Extra compatibility with Lua 5.1 (updated SWIG_init, docs, examples, test suite) + Removed name clash for static link of multiple modules + 07/05/2007: mgossage [lua] Fix a bug in SWIG_ALLOC_ARRAY() improved the error messages for incorrect arguments. diff --git a/Doc/Manual/Lua.html b/Doc/Manual/Lua.html index 1ecf058d7..ba77e8666 100644 --- a/Doc/Manual/Lua.html +++ b/Doc/Manual/Lua.html @@ -54,10 +54,7 @@ Lua is an extension programming language designed to support general procedural
-The current SWIG implementation is designed to work with Lua 5.0. It should work with later versions of Lua, but certainly not with Lua 4.0 due to substantial API changes. ((Currently SWIG generated code has only been tested on Windows with MingW, though given the nature of Lua, is should not have problems on other OS's)). It is possible to either static link or dynamic link a Lua module into the interpreter (normally Lua static links its libraries, as dynamic linking is not available on all platforms). -
--Note: Lua 5.1 (alpha) has just (as of September 05) been released. The current version of SWIG will produce wrappers which are compatible with Lua 5.1, though the dynamic loading mechanism has changed (see below). The configure script and makefiles should work correctly with with Lua 5.1, though some small tweaks may be needed. +The current SWIG implementation is designed to work with Lua 5.0.x and Lua 5.1.x. It should work with later versions of Lua, but certainly not with Lua 4.0 due to substantial API changes. ((Currently SWIG generated code has only been tested on Windows with MingW, though given the nature of Lua, is should not have problems on other OS's)). It is possible to either static link or dynamic link a Lua module into the interpreter (normally Lua static links its libraries, as dynamic linking is not available on all platforms).
-The name of the wrapper file is derived from the name of the input file. For example, if the input file is example.i, the name of the wrapper file is example_wrap.c. To change this, you can use the -o option. The wrappered module will export one function "int Example_Init(LuaState* L)" which must be called to register the module with the Lua interpreter. The name "Example_Init" depends upon the name of the module. Note: SWIG will automatically capitalise the module name, so "module example;" becomes "Example_Init". +The name of the wrapper file is derived from the name of the input file. For example, if the input file is example.i, the name of the wrapper file is example_wrap.c. To change this, you can use the -o option. The wrappered module will export one function "int luaopen_example(LuaState* L)" which must be called to register the module with the Lua interpreter. The name "luaopen_example" depends upon the name of the module.
-A much improved set of code can be found in the Lua distribution src/lua/lua.c. Include your module, just add the external declaration & add a #define LUA_EXTRALIBS {"example",Example_Init}, at the relevant place. +A much improved set of code can be found in the Lua distribution src/lua/lua.c. Include your module, just add the external declaration & add a #define LUA_EXTRALIBS {"example",luaopen_example}, at the relevant place.
The exact commands for doing this vary from platform to platform. Here is a possible set of commands of doing this: @@ -151,40 +148,39 @@ $ gcc -c example.c -o example.o $ gcc -shared -I/usr/include/lua -L/usr/lib/lua example_wrap.o example.o -o example.so
-You will also need an interpreter with the loadlib function (such as the default interpreter compiled with Lua). In order to dynamically load a module you must call the loadlib function with two parameters: the filename of the shared library, and the function exported by SWIG. Calling loadlib should return the function, which you then call to initialise the module +The wrappers produced by SWIG can be compiled and linked with Lua 5.1.x. The loading is extremely simple.
-my_init=loadlib("example.so","Example_Init") -- for Unix/Linux
---my_init=loadlib("example.dll","Example_Init") -- for Windows
+require("example")
++For those using Lua 5.0.x, you will also need an interpreter with the loadlib function (such as the default interpreter compiled with Lua). In order to dynamically load a module you must call the loadlib function with two parameters: the filename of the shared library, and the function exported by SWIG. Calling loadlib should return the function, which you then call to initialise the module +
+
+my_init=loadlib("example.so","luaopen_example") -- for Unix/Linux
+--my_init=loadlib("example.dll","luaopen_example") -- for Windows
assert(my_init) -- name sure its not nil
my_init() -- call the init fn of the lib
Or can be done in a single line of Lua code
+
+assert(loadlib("example.so","luaopen_example"))()
+
-assert(loadlib("example.so","Example_Init"))()
-
-Update for Lua 5.1 (alpha):
-The wrappers produced by SWIG can be compiled and linked with Lua 5.1. The loading is now much simpler.
-
-require("example")
-If the code didn't work, don't panic. The best thing to do is to copy the module and your interpreter into a single directory and then execute the interpreter and try to manually load the module (take care, all this code is case sensitive).
-a,b,c=loadlib("example.so","Example_Init") -- for Unix/Linux
---a,b,c=loadlib("example.dll","Example_Init") -- for Windows
+a,b,c=package.loadlib("example.so","luaopen_example") -- for Unix/Linux
+--a,b,c=package.loadlib("example.dll","luaopen_example") -- for Windows
print(a,b,c)
-Note: for Lua 5.1:
-The loadlib() function has been moved into the package table, so you must use package.loadlib() instead.
+Note: for Lua 5.0:
+The loadlib() function is in the global namespace, not in package. So its just loadlib().
if 'a' is a function, this its all working fine, all you need to do is call it diff --git a/Examples/lua/class/runme.lua b/Examples/lua/class/runme.lua index 3104abe7a..2c3ad8ced 100644 --- a/Examples/lua/class/runme.lua +++ b/Examples/lua/class/runme.lua @@ -6,7 +6,7 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then -- lua5.0 doesnt have a nice way to do this - lib=loadlib('example.dll','Example_Init') or loadlib('example.so','Example_Init') + lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else -- lua 5.1 does diff --git a/Examples/lua/constants/runme.lua b/Examples/lua/constants/runme.lua index b3b8d3e8a..751e7d623 100644 --- a/Examples/lua/constants/runme.lua +++ b/Examples/lua/constants/runme.lua @@ -3,7 +3,7 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then -- lua5.0 doesnt have a nice way to do this - lib=loadlib('example.dll','Example_Init') or loadlib('example.so','Example_Init') + lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else -- lua 5.1 does diff --git a/Examples/lua/funcptr3/runme.lua b/Examples/lua/funcptr3/runme.lua index 25010b0e2..b78c504ef 100644 --- a/Examples/lua/funcptr3/runme.lua +++ b/Examples/lua/funcptr3/runme.lua @@ -1,7 +1,7 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then -- lua5.0 doesnt have a nice way to do this - lib=loadlib('example.dll','Example_Init') or loadlib('example.so','Example_Init') + lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else -- lua 5.1 does diff --git a/Examples/lua/functest/runme.lua b/Examples/lua/functest/runme.lua index 1ea11489d..65b3cc215 100644 --- a/Examples/lua/functest/runme.lua +++ b/Examples/lua/functest/runme.lua @@ -1,7 +1,7 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then -- lua5.0 doesnt have a nice way to do this - lib=loadlib('example.dll','Example_Init') or loadlib('example.so','Example_Init') + lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else -- lua 5.1 does diff --git a/Examples/lua/functor/runme.lua b/Examples/lua/functor/runme.lua index e0e44c129..66741041c 100644 --- a/Examples/lua/functor/runme.lua +++ b/Examples/lua/functor/runme.lua @@ -2,7 +2,7 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then -- lua5.0 doesnt have a nice way to do this - lib=loadlib('example.dll','Example_Init') or loadlib('example.so','Example_Init') + lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else -- lua 5.1 does diff --git a/Examples/lua/import/runme.lua b/Examples/lua/import/runme.lua index 2409d436b..9cd7ae06c 100644 --- a/Examples/lua/import/runme.lua +++ b/Examples/lua/import/runme.lua @@ -4,14 +4,14 @@ print("Testing the %import directive") if string.sub(_VERSION,1,7)=='Lua 5.0' then -- lua5.0 doesnt have a nice way to do this - function loadit(a,b) - lib=loadlib(a..':dll',b) or loadlib(a..':so',b) + function loadit(a) + lib=loadlib(a..'.dll','luaopen_'..a) or loadlib(a..'.so','luaopen_'..a) assert(lib)() end - loadit('base','Base_Init') - loadit('foo','Foo_Init') - loadit('bar','Bar_Init') - loadit('spam','Spam_Init') + loadit('base') + loadit('foo') + loadit('bar') + loadit('spam') else -- lua 5.1 does require 'base' diff --git a/Examples/lua/pointer/runme.lua b/Examples/lua/pointer/runme.lua index 722c54b94..8deee67e6 100644 --- a/Examples/lua/pointer/runme.lua +++ b/Examples/lua/pointer/runme.lua @@ -1,7 +1,7 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then -- lua5.0 doesnt have a nice way to do this - lib=loadlib('example.dll','Example_Init') or loadlib('example.so','Example_Init') + lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else -- lua 5.1 does diff --git a/Examples/lua/simple/runme.lua b/Examples/lua/simple/runme.lua index 9111db0f3..1e5a139c8 100644 --- a/Examples/lua/simple/runme.lua +++ b/Examples/lua/simple/runme.lua @@ -1,7 +1,7 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then -- lua5.0 doesnt have a nice way to do this - lib=loadlib('example.dll','Example_Init') or loadlib('example.so','Example_Init') + lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else -- lua 5.1 does diff --git a/Examples/lua/variables/runme.lua b/Examples/lua/variables/runme.lua index ad0b24ed4..05b2d3fbf 100644 --- a/Examples/lua/variables/runme.lua +++ b/Examples/lua/variables/runme.lua @@ -1,7 +1,7 @@ ---- importing ---- if string.sub(_VERSION,1,7)=='Lua 5.0' then -- lua5.0 doesnt have a nice way to do this - lib=loadlib('example.dll','Example_Init') or loadlib('example.so','Example_Init') + lib=loadlib('example.dll','luaopen_example') or loadlib('example.so','luaopen_example') assert(lib)() else -- lua 5.1 does diff --git a/Examples/test-suite/lua/import.lua b/Examples/test-suite/lua/import.lua index b2a40b017..eaab3b400 100644 --- a/Examples/test-suite/lua/import.lua +++ b/Examples/test-suite/lua/import.lua @@ -3,36 +3,22 @@ -- the lua 5.1 loading mechanism is simplicity itself -- for now we need a bridge which will use the correct verion -function import_5_0(module) +function import_5_0(name) -- imports the file into the program -- for a module 'example' -- this must load 'example.dll' or 'example.so' - -- and look for the fn 'Example_Init()' (note the capitalisation) - if rawget(_G,module)~=nil then return end -- module appears to be loaded + -- and look for the fn 'luaopen_example()' + if rawget(_G,name)~=nil then return end -- module appears to be loaded - -- capitialising the first letter - local c=string.upper(string.sub(module,1,1)) - local fnname=c..string.sub(module,2).."_Init" - - local suffix,lib - -- note: as there seems to be no way in lua to determine the platform - -- we will try loading all possible names - -- providing one works, we can load - for _,suffix in pairs{".dll",".so"} do - lib=loadlib(module..suffix,fnname) - if lib then -- found - break - end - end - assert(lib,"error loading module:"..module) + local lib=loadlib(name..'.dll','luaopen_'..name) or loadlib(name..'.so','luaopen_'..name) + assert(lib,"error loading module:"..name) lib() -- execute the function: initalising the lib - local m=rawget(_G,module) -- gets the module object - assert(m~=nil,"no module table found") + assert(rawget(_G,name)~=nil,"no module table found") end -function import_5_1(module) - require(module) +function import_5_1(name) + require(name) end if string.sub(_VERSION,1,7)=='Lua 5.0' then diff --git a/Lib/lua/luaruntime.swg b/Lib/lua/luaruntime.swg index 07a3daef6..afb516a89 100644 --- a/Lib/lua/luaruntime.swg +++ b/Lib/lua/luaruntime.swg @@ -15,11 +15,11 @@ %insert(initbeforefunc) %{ /* Forward declaration of where the user's %init{} gets inserted */ +void SWIG_init_user(lua_State* L ); + #ifdef __cplusplus extern "C" { #endif -void SWIG_init_user(lua_State* L ); - /* this is the initialization function added at the very end of the code the function is always called SWIG_init, but an eariler #define will rename it @@ -27,63 +27,40 @@ void SWIG_init_user(lua_State* L ); SWIGEXPORT int SWIG_init(lua_State* L) { int i; - /* start with global table */ lua_pushvalue(L,LUA_GLOBALSINDEX); - + /* SWIG's internal initalisation */ SWIG_InitializeModule((void*)L); SWIG_PropagateClientData(); - - /* invoke user-specific initialization */ - SWIG_init_user(L); - /* add a global fn */ SWIG_Lua_add_function(L,"swig_type",SWIG_Lua_type); SWIG_Lua_add_function(L,"swig_equals",SWIG_Lua_equal); - /* begin the module (its a table with the same name as the module) */ SWIG_Lua_module_begin(L,SWIG_name); /* add commands/functions */ for (i = 0; swig_commands[i].name; i++){ SWIG_Lua_module_add_function(L,swig_commands[i].name,swig_commands[i].func); } - /*luaL_openlib(L,NULL,swig_commands,0);*/ - /* all in one */ - /*luaL_openlib(L,SWIG_name,swig_commands,0);*/ /* add variables */ for (i = 0; swig_variables[i].name; i++){ SWIG_Lua_module_add_variable(L,swig_variables[i].name,swig_variables[i].get,swig_variables[i].set); } - /* additional registration structs & classes in lua: */ for (i = 0; swig_types[i]; i++){ if (swig_types[i]->clientdata){ SWIG_Lua_class_register(L,(swig_lua_class*)(swig_types[i]->clientdata)); } } - /* constants */ SWIG_Lua_InstallConstants(L,swig_constants); - + /* invoke user-specific initialization */ + SWIG_init_user(L); /* end module */ - /*SWIG_Lua_module_end(L);*/ lua_pop(L,1); /* tidy stack (remove module table)*/ lua_pop(L,1); /* tidy stack (remove global table)*/ - return 1; } -/* Lua 5.1 has a different name for importing libraries -luaopen_XXX, where XXX is the name of the module (not capitalised) -this function will allow Lua 5.1 to import correctly. -There is a #define in the wrapper to rename 'SWIG_import' to the correct name -*/ - -SWIGEXPORT int SWIG_import(lua_State* L) -{ - return SWIG_init(L); -} - #ifdef __cplusplus } #endif diff --git a/Lib/lua/luatypemaps.swg b/Lib/lua/luatypemaps.swg index 5efef21e7..74264b517 100644 --- a/Lib/lua/luatypemaps.swg +++ b/Lib/lua/luatypemaps.swg @@ -358,10 +358,10 @@ $1=&temp;%} #ifdef __cplusplus %ignore swig::LANGUAGE_OBJ; -%inline %{ +//%inline %{ +%{ namespace swig { typedef struct{} LANGUAGE_OBJ; -//typedef void* LANGUAGE_OBJ; } %} diff --git a/Source/Modules/lua.cxx b/Source/Modules/lua.cxx index e0a62d8f8..ae69a8451 100644 --- a/Source/Modules/lua.cxx +++ b/Source/Modules/lua.cxx @@ -248,23 +248,21 @@ NEW LANGUAGE NOTE:END ************************************************/ // Printf(f_runtime, "#define SWIG_NOINCLUDE\n"); // } - String *init_name = NewStringf("%(title)s_Init", module); - Printf(f_header, "#define SWIG_init %s\n", init_name); - Printf(f_header, "#define SWIG_name \"%s\"\n", module); + //String *init_name = NewStringf("%(title)s_Init", module); + //Printf(f_header, "#define SWIG_init %s\n", init_name); + //Printf(f_header, "#define SWIG_name \"%s\"\n", module); /* SWIG_import is a special function name for importing within Lua5.1 */ - Printf(f_header, "#define SWIG_import luaopen_%s\n\n", module); + //Printf(f_header, "#define SWIG_import luaopen_%s\n\n", module); + Printf(f_header, "#define SWIG_name \"%s\"\n", module); + Printf(f_header, "#define SWIG_init luaopen_%s\n", module); + Printf(f_header, "#define SWIG_init_user luaopen_%s_user\n\n", module); Printf(s_cmd_tab, "\nstatic const struct luaL_reg swig_commands[] = {\n"); Printf(s_var_tab, "\nstatic swig_lua_var_info swig_variables[] = {\n"); Printf(s_const_tab, "\nstatic swig_lua_const_info swig_constants[] = {\n"); Printf(f_wrappers, "#ifdef __cplusplus\nextern \"C\" {\n#endif\n"); - /* Change naming scheme for constructors and destructors */ -// Swig_name_register("construct","%c_create"); -// Swig_name_register("destroy","%c_destroy"); - /* %init code inclusion, effectively in the SWIG_init function */ - Printf(f_init, "#ifdef __cplusplus\nextern \"C\"\n#endif\n"); Printf(f_init, "void SWIG_init_user(lua_State* L)\n{\n"); Language::top(n); Printf(f_init, "}\n"); @@ -278,10 +276,6 @@ NEW LANGUAGE NOTE:END ************************************************/ Printv(f_wrappers, s_cmd_tab, s_var_tab, s_const_tab, NIL); SwigType_emit_type_table(f_runtime, f_wrappers); - // - /* Close the initialization function */ -// Printf(f_init, "}\n"); - /* NEW LANGUAGE NOTE:*********************************************** this basically combines several of the strings together and then writes it all to a file