[lua] extras compability for lua 5.1, fixed a static link name conflict

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9864 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
Mark Gossage 2007-07-10 09:30:49 +00:00
commit f87371fe8c
15 changed files with 61 additions and 104 deletions

View file

@ -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.

View file

@ -54,10 +54,7 @@ Lua is an extension programming language designed to support general procedural
<p>
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).
</p>
<p>
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).
</p>
<H2><a name="Lua_nn3"></a>22.2 Running SWIG</H2>
@ -89,7 +86,7 @@ $ swig -c++ -lua example.i
This creates a C/C++ source file <tt>example_wrap.c</tt> or <tt>example_wrap.cxx</tt>. The generated C source file contains the low-level wrappers that need to be compiled and linked with the rest of your C/C++ application to create an extension module.
</p>
<p>
The name of the wrapper file is derived from the name of the input file. For example, if the input file is <tt>example.i</tt>, the name of the wrapper file is <tt>example_wrap.c</tt>. To change this, you can use the -o option. The wrappered module will export one function <tt>"int Example_Init(LuaState* L)"</tt> 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 <tt>"module example;"</tt> becomes <tt>"Example_Init"</tt>.
The name of the wrapper file is derived from the name of the input file. For example, if the input file is <tt>example.i</tt>, the name of the wrapper file is <tt>example_wrap.c</tt>. To change this, you can use the -o option. The wrappered module will export one function <tt>"int luaopen_example(LuaState* L)"</tt> which must be called to register the module with the Lua interpreter. The name "luaopen_example" depends upon the name of the module.
</p>
<H3><a name="Lua_nn4"></a>22.2.1 Compiling and Linking and Interpreter</H3>
@ -103,7 +100,7 @@ Normally Lua is embedded into another program and will be statically linked. An
#include "lualib.h"
#include "lauxlib.h"
extern int Example_Init(LuaState* L); // declare the wrapped module
extern int luaopen_example(LuaState* L); // declare the wrapped module
int main(int argc,char* argv[])
{
@ -115,7 +112,7 @@ int main(int argc,char* argv[])
}
L=lua_open();
luaopen_base(L); // load basic libs (eg. print)
Example_Init(L); // load the wrappered module
luaopen_example(L); // load the wrappered module
if (luaL_loadfile(L,argv[1])==0) // load and run the file
lua_pcall(L,0,0,0);
else
@ -125,7 +122,7 @@ int main(int argc,char* argv[])
}
</pre></div>
<p>
A much improved set of code can be found in the Lua distribution <tt>src/lua/lua.c</tt>. Include your module, just add the external declaration &amp; add a <tt>#define LUA_EXTRALIBS {"example",Example_Init}</tt>, at the relevant place.
A much improved set of code can be found in the Lua distribution <tt>src/lua/lua.c</tt>. Include your module, just add the external declaration &amp; add a <tt>#define LUA_EXTRALIBS {"example",luaopen_example}</tt>, at the relevant place.
</p>
<p>
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
</pre></div>
<p>
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.
</p>
<div class="targetlang"><pre>
my_init=loadlib("example.so","Example_Init") -- for Unix/Linux
--my_init=loadlib("example.dll","Example_Init") -- for Windows
require("example")
</pre></div>
<p>
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
</p>
<div class="targetlang"><pre>
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
</pre></div>
<p>
Or can be done in a single line of Lua code
</p>
<div class="targetlang"><pre>
assert(loadlib("example.so","luaopen_example"))()
</pre></div>
<div class="targetlang"><pre>
assert(loadlib("example.so","Example_Init"))()
</pre></div>
<p>
Update for Lua 5.1 (alpha):<br>
The wrappers produced by SWIG can be compiled and linked with Lua 5.1. The loading is now much simpler.
</p>
<div class="targetlang"><pre>
require("example")
</pre></div>
<p>
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).
</p>
<div class="targetlang"><pre>
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)
</pre></div>
<p>
Note: for Lua 5.1:<br>
The loadlib() function has been moved into the package table, so you must use package.loadlib() instead.
Note: for Lua 5.0:<br>
The loadlib() function is in the global namespace, not in package. So its just loadlib().
</p>
<p>
if 'a' is a function, this its all working fine, all you need to do is call it

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -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'

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -358,10 +358,10 @@ $1=&temp;%}
#ifdef __cplusplus
%ignore swig::LANGUAGE_OBJ;
%inline %{
//%inline %{
%{
namespace swig {
typedef struct{} LANGUAGE_OBJ;
//typedef void* LANGUAGE_OBJ;
}
%}

View file

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