mirror of https://github.com/swig/swig
[lua] Fix a bug in the class hierachy code, where the methods were not propagated,
if the name ordering was in a certain order. Added new example programs (dual, embed) and runtime tests for test-suite. git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@10177 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
parent
575efcdd53
commit
89c3acea19
|
@ -1,6 +1,11 @@
|
|||
Version 1.3.34 (in progress)
|
||||
============================
|
||||
|
||||
12/04/2007: mgossage
|
||||
[lua] Fix a bug in the class hierachy code, where the methods were not propagated,
|
||||
if the name ordering was in a certain order.
|
||||
Added new example programs (dual, embed) and runtime tests for test-suite.
|
||||
|
||||
11/30/2007: wsfulton
|
||||
Fix using statements using a base class method where the methods were overloaded.
|
||||
Depending on the order of the using statements and method declarations, these
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
# see top-level Makefile.in
|
||||
class
|
||||
constants
|
||||
dual
|
||||
embed
|
||||
funcptr3
|
||||
functest
|
||||
functor
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
TOP = ../..
|
||||
SWIG = $(TOP)/../preinst-swig
|
||||
TARGET = dual
|
||||
CXXSRCS = example2_wrap.cxx
|
||||
INTERFACE = dual.i
|
||||
LUA_INTERP = dual.cpp
|
||||
|
||||
# this is a little different ot normal as we need to static link two modules and a custom intepreter
|
||||
# we need the external runtime, then swig examples2, and build the module as normal
|
||||
all::
|
||||
$(SWIG) -lua -external-runtime
|
||||
$(SWIG) -c++ -lua $(SWIGOPT) example2.i
|
||||
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \
|
||||
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='example.i' LUA_INTERP='$(LUA_INTERP)' lua_static_cpp
|
||||
|
||||
clean::
|
||||
$(MAKE) -f $(TOP)/Makefile lua_clean
|
||||
|
||||
check: all
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
dual.cpp a test for multiple modules and multiple intrepreters staticly linked together.
|
||||
|
||||
Earlier version of lua bindings for SWIG would fail if staticly linked.
|
||||
|
||||
What is happening is as follows:
|
||||
example.i declares a type Foo
|
||||
examples2.i declares Bar
|
||||
|
||||
The first lua state will load example.i
|
||||
and check to see if types Foo and Bar are registered with it
|
||||
(Foo should be & Bar should not)
|
||||
|
||||
The second lua state will load example2.i
|
||||
and check to see if types Foo and Bar are registered with it
|
||||
(Bar should be & Foo should not)
|
||||
|
||||
Note: Though both the modules exist and are loaded, they are not linked together,
|
||||
as they are connected to seperate lua interpreters.
|
||||
|
||||
When the third lua state loads both example.i and example2.i,
|
||||
the two modules are now linked together, and all can now find
|
||||
both Foo and Bar.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "swigluarun.h" // the swig runtimes
|
||||
|
||||
// the 2 libraries which are wrappered via SWIG
|
||||
extern "C" int luaopen_example(lua_State*L);
|
||||
extern "C" int luaopen_example2(lua_State*L);
|
||||
|
||||
#define DEBUG(X) {printf(X);fflush(stdout);}
|
||||
#define DEBUG2(X,Y) {printf(X,Y);fflush(stdout);}
|
||||
#define DEBUG3(X,Y,Z) {printf(X,Y,Z);fflush(stdout);}
|
||||
|
||||
void testModule(lua_State *L)
|
||||
{
|
||||
swig_type_info *pTypeInfo=0,*pTypeInfo2=0;
|
||||
swig_module_info *pModule=0;
|
||||
pModule=SWIG_GetModule(L);
|
||||
DEBUG2(" SWIG_GetModule() returns %p\n",pModule)
|
||||
if(pModule==0) return;
|
||||
pTypeInfo = SWIG_TypeQuery(L,"Foo *");
|
||||
DEBUG2(" Type (Foo*) is %s\n",pTypeInfo==0?"unknown":"known");
|
||||
DEBUG3(" Module %p typeinfo(Foo*) %p\n",pModule,pTypeInfo);
|
||||
pTypeInfo2 = SWIG_TypeQuery(L,"Bar *");
|
||||
DEBUG2(" Type (Bar*) is %s\n",pTypeInfo2==0?"unknown":"known");
|
||||
DEBUG3(" Module %p typeinfo(Bar*) %p\n",pModule,pTypeInfo2);
|
||||
}
|
||||
|
||||
int main(int argc,char* argv[])
|
||||
{
|
||||
lua_State *L1=0,*L2=0,*L3=0;
|
||||
|
||||
printf("This is a test of having two SWIG'ed modules and three lua states\n"
|
||||
"statically linked together.\n"
|
||||
"Its mainly to check that all the types are correctly managed\n\n");
|
||||
|
||||
DEBUG("creating lua states(L1,L2,L3)");
|
||||
L1=lua_open();
|
||||
L2=lua_open();
|
||||
L3=lua_open();
|
||||
DEBUG("ok\n\n");
|
||||
|
||||
DEBUG("luaopen_example(L1)..");
|
||||
luaopen_example(L1);
|
||||
DEBUG("ok\n");
|
||||
|
||||
DEBUG("Testing Module L1\n");
|
||||
DEBUG("This module should know about Foo* but not Bar*\n");
|
||||
testModule(L1);
|
||||
DEBUG("End Testing Module L1\n\n");
|
||||
|
||||
DEBUG("luaopen_example2(L2)..");
|
||||
luaopen_example2(L2);
|
||||
DEBUG("ok\n");
|
||||
|
||||
DEBUG("Testing Module L2\n");
|
||||
DEBUG("This module should know about Bar* but not Foo*\n");
|
||||
testModule(L2);
|
||||
DEBUG("End Testing Module L2\n\n");
|
||||
|
||||
DEBUG("luaopen_example(L3)..");
|
||||
luaopen_example(L3);
|
||||
DEBUG("ok\n");
|
||||
DEBUG("luaopen_example2(L3)..");
|
||||
luaopen_example2(L3);
|
||||
DEBUG("ok\n");
|
||||
|
||||
DEBUG("Testing Module L3\n");
|
||||
DEBUG("This module should know about Foo* and Bar*\n");
|
||||
testModule(L3);
|
||||
DEBUG("End Testing Module L3\n\n");
|
||||
|
||||
DEBUG("Testing Module L1 again\n");
|
||||
DEBUG("It now should know about Foo* and Bar*\n");
|
||||
testModule(L1);
|
||||
DEBUG("End Testing Module L1 again\n\n");
|
||||
|
||||
DEBUG("close all..");
|
||||
lua_close(L1);
|
||||
lua_close(L2);
|
||||
lua_close(L3);
|
||||
DEBUG("ok, exiting\n");
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
/* File : example.i */
|
||||
%module example
|
||||
|
||||
%inline %{
|
||||
|
||||
struct Foo{
|
||||
int i;
|
||||
};
|
||||
|
||||
%}
|
|
@ -0,0 +1,10 @@
|
|||
/* File : example2.i */
|
||||
%module example2
|
||||
|
||||
%inline %{
|
||||
|
||||
struct Bar{
|
||||
int i;
|
||||
};
|
||||
|
||||
%}
|
|
@ -0,0 +1,18 @@
|
|||
TOP = ../..
|
||||
SWIG = $(TOP)/../preinst-swig
|
||||
TARGET = embed
|
||||
SRCS = example.c
|
||||
INTERFACE = example.i
|
||||
LUA_INTERP = embed.c
|
||||
|
||||
# this is a little different to normal as we have our own special interpreter
|
||||
# which we want to static link
|
||||
all::
|
||||
$(MAKE) -f $(TOP)/Makefile $(SWIGLIB) SRCS='$(SRCS)' SWIG='$(SWIG)' \
|
||||
SWIGOPT='$(SWIGOPT)' TARGET='$(TARGET)' INTERFACE='example.i' LUA_INTERP='$(LUA_INTERP)' lua_static
|
||||
|
||||
clean::
|
||||
$(MAKE) -f $(TOP)/Makefile lua_clean
|
||||
|
||||
check: all
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/* embed.c a simple test for an embeded interpreter
|
||||
|
||||
The idea is that we wrapper a few simple function (example.c)
|
||||
and write our own app to call it.
|
||||
|
||||
What it will do is load the wrappered lib, load runme.lua and then call some functions.
|
||||
To make life easier, all the printf's have either [C] or [Lua] at the start
|
||||
so you can see where they are coming from.
|
||||
|
||||
We will be using the luaL_dostring()/lua_dostring() function to call into lua
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <lua.h>
|
||||
#include <lauxlib.h>
|
||||
#include <lualib.h>
|
||||
|
||||
/* the SWIG wrappered library */
|
||||
extern int luaopen_example(lua_State*L);
|
||||
|
||||
/* a really simple way of calling lua from C
|
||||
just give it a lua state & a string to execute
|
||||
Unfortunately lua keeps changing its API's.
|
||||
In lua 5.0.X its lua_dostring()
|
||||
In lua 5.1.X its luaL_dostring()
|
||||
so we have a few extra compiles
|
||||
*/
|
||||
int dostring(lua_State *L, char* str)
|
||||
{
|
||||
int ok;
|
||||
#if (defined(LUA_VERSION_NUM) && (LUA_VERSION_NUM>=501))
|
||||
ok=luaL_dostring(L,str); /* looks like this is lua 5.1.X or later, good */
|
||||
#else
|
||||
ok=lua_dostring(L,str); /* might be lua 5.0.x, using lua_dostring */
|
||||
#endif
|
||||
if (ok!=0)
|
||||
printf("[C] ERROR in dostring: %s\n",lua_tostring(L,-1));
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
int main(int argc,char* argv[])
|
||||
{
|
||||
lua_State *L;
|
||||
int ok;
|
||||
printf("[C] Welcome to the simple embedded lua example\n");
|
||||
printf("[C] We are in C\n");
|
||||
printf("[C] opening a lua state & loading the libraries\n");
|
||||
L=lua_open();
|
||||
luaopen_base(L);
|
||||
luaopen_string(L);
|
||||
luaopen_math(L);
|
||||
printf("[C] now loading the SWIG wrappered library\n");
|
||||
luaopen_example(L);
|
||||
printf("[C] all looks ok\n");
|
||||
printf("\n");
|
||||
printf("[C] lets load the file 'runme.lua'\n");
|
||||
printf("[C] any lua code in this file will be executed\n");
|
||||
if (luaL_loadfile(L, "runme.lua") || lua_pcall(L, 0, 0, 0))
|
||||
{
|
||||
printf("[C] ERROR: cannot run lua file: %s",lua_tostring(L, -1));
|
||||
exit(3);
|
||||
}
|
||||
printf("[C] We are now back in C, all looks ok\n");
|
||||
printf("\n");
|
||||
printf("[C] lets call the function 'do_tests()'\n");
|
||||
ok=dostring(L,"do_tests()");
|
||||
printf("[C] We are back in C, the dostring() function returned %d\n",ok);
|
||||
printf("\n");
|
||||
printf("[C] Lets call lua again, but create an error\n");
|
||||
ok=dostring(L,"no_such_function()");
|
||||
printf("[C] We are back in C, the dostring() function returned %d\n",ok);
|
||||
printf("[C] it should also have returned 1 and printed an error message\n");
|
||||
printf("\n");
|
||||
printf("[C] Lets call lua again, calling the greeting function\n");
|
||||
ok=dostring(L,"call_greeting()");
|
||||
printf("[C] This was C=>Lua=>C (getting a bit complex)\n");
|
||||
printf("\n");
|
||||
printf("[C] all finished, closing the lua state\n");
|
||||
lua_close(L);
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
/* File : example.c */
|
||||
|
||||
/* A global variable */
|
||||
double Foo = 3.0;
|
||||
|
||||
/* Compute the greatest common divisor of positive integers */
|
||||
int gcd(int x, int y) {
|
||||
int g;
|
||||
g = y;
|
||||
while (x > 0) {
|
||||
g = x;
|
||||
x = y % x;
|
||||
y = g;
|
||||
}
|
||||
return g;
|
||||
}
|
||||
|
||||
void greeting()
|
||||
{
|
||||
printf("Hello from the C function 'greeting'\n");
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
/* File : example.i */
|
||||
%module example
|
||||
|
||||
%inline %{
|
||||
extern int gcd(int x, int y);
|
||||
extern double Foo;
|
||||
extern void greeting();
|
||||
%}
|
|
@ -0,0 +1,40 @@
|
|||
print "[lua] This is runme.lua"
|
||||
-- test program for embeded lua
|
||||
-- we do not need to load the library, as it was already in the intrepreter
|
||||
-- but lets check anyway
|
||||
assert(type(example)=='table',"Don't appear to have loaded the example module")
|
||||
|
||||
-- a test function to run the tests
|
||||
function do_tests()
|
||||
print("[lua] We are now in Lua, inside the do_tests() function")
|
||||
print("[lua] We will be calling example.gcd() and changing example.Foo")
|
||||
-- Call our gcd() function
|
||||
x = 42
|
||||
y = 105
|
||||
g = example.gcd(x,y)
|
||||
print("[lua] The gcd of",x,"and",y,"is",g)
|
||||
|
||||
-- Manipulate the Foo global variable
|
||||
|
||||
-- Output its current value
|
||||
print("[lua] Foo = ", example.Foo)
|
||||
|
||||
-- Change its value
|
||||
example.Foo = 3.1415926
|
||||
|
||||
-- See if the change took effect
|
||||
print("[lua] Foo = ", example.Foo)
|
||||
print("[lua] ending the do_tests() function")
|
||||
end
|
||||
|
||||
function call_greeting()
|
||||
print("[lua] We are now in Lua, inside the call_greeting() function")
|
||||
example.greeting()
|
||||
print("[lua] ending the call_greeting() function")
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
require("import") -- the import fn
|
||||
-- note: need to import the base class module before the derived class
|
||||
-- this is because if the derived class is imported first it doesn't get the base class methods
|
||||
import("multi_import_b") -- import code
|
||||
import("multi_import_a") -- import code
|
||||
|
||||
x = multi_import_b.XXX()
|
||||
assert(x:testx() == 0)
|
||||
|
||||
y = multi_import_b.YYY()
|
||||
assert(y:testx() == 0)
|
||||
assert(y:testy() == 1)
|
||||
|
||||
z = multi_import_a.ZZZ()
|
||||
assert(z:testx() == 0)
|
||||
assert(z:testz() == 2)
|
|
@ -327,7 +327,7 @@ SWIGINTERN int SWIG_Lua_class_get(lua_State* L)
|
|||
lua_pushvalue(L,2); /* key */
|
||||
lua_rawget(L,-2); /* look for the fn */
|
||||
lua_remove(L,-2); /* stack tidy, remove .fn table */
|
||||
if (lua_iscfunction(L,-1))
|
||||
if (lua_isfunction(L,-1)) /* note: if its a C function or lua function */
|
||||
{ /* found it so return the fn & let lua call it */
|
||||
lua_remove(L,-2); /* stack tidy, remove metatable */
|
||||
return 1;
|
||||
|
@ -490,6 +490,28 @@ SWIGINTERN void SWIG_Lua_add_class_details(lua_State* L,swig_lua_class* clss)
|
|||
}
|
||||
}
|
||||
|
||||
/* set up the base classes pointers.
|
||||
Each class structure has a list of pointers to the base class structures.
|
||||
This function fills them.
|
||||
It cannot be done at compile time, as this will not work with hireachies
|
||||
spread over more than one swig file.
|
||||
Therefore it must be done at runtime, querying the SWIG type system.
|
||||
*/
|
||||
SWIGINTERN void SWIG_Lua_init_base_class(lua_State* L,swig_lua_class* clss)
|
||||
{
|
||||
int i=0;
|
||||
swig_module_info* module=SWIG_GetModule(L);
|
||||
for(i=0;clss->base_names[i];i++)
|
||||
{
|
||||
if (clss->bases[i]==0) /* not found yet */
|
||||
{
|
||||
/* lookup and cache the base class */
|
||||
swig_type_info *info = SWIG_TypeQueryModule(module,module,clss->base_names[i]);
|
||||
if (info) clss->bases[i] = (swig_lua_class *) info->clientdata;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* performs the entire class registration process */
|
||||
SWIGINTERN void SWIG_Lua_class_register(lua_State* L,swig_lua_class* clss)
|
||||
{
|
||||
|
@ -528,20 +550,6 @@ SWIGINTERN void SWIG_Lua_class_register(lua_State* L,swig_lua_class* clss)
|
|||
lua_rawset(L,-3); /* metatable into registry */
|
||||
lua_pop(L,1); /* tidy stack (remove registry) */
|
||||
|
||||
/* set up the class base classes
|
||||
we need to check the names of the classes to see if the base class exists
|
||||
if so, we need to set up the pointer to it */
|
||||
swig_module_info* module=SWIG_GetModule(L);
|
||||
for(i=0;clss->base_names[i];i++)
|
||||
{
|
||||
if (clss->bases[i]==0) /* not found yet */
|
||||
{
|
||||
/* lookup and cache the base class */
|
||||
swig_type_info *info = SWIG_TypeQueryModule(module,module,clss->base_names[i]);
|
||||
if (info) clss->bases[i] = (swig_lua_class *) info->clientdata;
|
||||
}
|
||||
}
|
||||
|
||||
SWIG_Lua_get_class_metatable(L,clss->name);
|
||||
SWIG_Lua_add_class_details(L,clss); /* recursive adding of details (atts & ops) */
|
||||
lua_pop(L,1); /* tidy stack (remove class metatable) */
|
||||
|
|
|
@ -45,7 +45,13 @@ SWIGEXPORT int SWIG_init(lua_State* L)
|
|||
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: */
|
||||
/* set up base class pointers (the hierachy) */
|
||||
for (i = 0; swig_types[i]; i++){
|
||||
if (swig_types[i]->clientdata){
|
||||
SWIG_Lua_init_base_class(L,(swig_lua_class*)(swig_types[i]->clientdata));
|
||||
}
|
||||
}
|
||||
/* 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));
|
||||
|
|
Loading…
Reference in New Issue