From 8350c724f5233c240e00dd3bd8930993e83d72ee Mon Sep 17 00:00:00 2001 From: Mark Gossage Date: Thu, 6 Mar 2008 09:44:48 +0000 Subject: [lua] updated docs for exceptions added new examples (exception,embed2) update typmaps git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@10300 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- Examples/lua/check.list | 2 + Examples/lua/embed/embed.c | 170 +++++++++++++++--------------- Examples/lua/embed/example.c | 45 ++++---- Examples/lua/embed2/Makefile | 18 ++++ Examples/lua/embed2/embed2.c | 221 +++++++++++++++++++++++++++++++++++++++ Examples/lua/embed2/example.c | 22 ++++ Examples/lua/embed2/example.i | 8 ++ Examples/lua/embed2/runme.lua | 27 +++++ Examples/lua/exception/Makefile | 19 ++++ Examples/lua/exception/example.h | 53 ++++++++++ Examples/lua/exception/example.i | 17 +++ Examples/lua/exception/runme.lua | 63 +++++++++++ 12 files changed, 557 insertions(+), 108 deletions(-) create mode 100644 Examples/lua/embed2/Makefile create mode 100644 Examples/lua/embed2/embed2.c create mode 100644 Examples/lua/embed2/example.c create mode 100644 Examples/lua/embed2/example.i create mode 100644 Examples/lua/embed2/runme.lua create mode 100644 Examples/lua/exception/Makefile create mode 100644 Examples/lua/exception/example.h create mode 100644 Examples/lua/exception/example.i create mode 100644 Examples/lua/exception/runme.lua (limited to 'Examples/lua') diff --git a/Examples/lua/check.list b/Examples/lua/check.list index f61e2544f..d28b1342a 100644 --- a/Examples/lua/check.list +++ b/Examples/lua/check.list @@ -3,6 +3,8 @@ class constants dual embed +embed2 +exception funcptr3 functest functor diff --git a/Examples/lua/embed/embed.c b/Examples/lua/embed/embed.c index 2f8d6555e..55ea099be 100644 --- a/Examples/lua/embed/embed.c +++ b/Examples/lua/embed/embed.c @@ -1,85 +1,85 @@ -/* 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 -#include - -#include -#include -#include - -/* 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; -} +/* 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 +#include + +#include +#include +#include + +/* 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; +} diff --git a/Examples/lua/embed/example.c b/Examples/lua/embed/example.c index 9ca71ee04..c6c6d7ba1 100644 --- a/Examples/lua/embed/example.c +++ b/Examples/lua/embed/example.c @@ -1,23 +1,22 @@ -/* File : example.c */ - -#include - -/* 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"); -} +/* File : example.c */ + +#include + +/* 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"); +} diff --git a/Examples/lua/embed2/Makefile b/Examples/lua/embed2/Makefile new file mode 100644 index 000000000..5f267d94d --- /dev/null +++ b/Examples/lua/embed2/Makefile @@ -0,0 +1,18 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +TARGET = embed2 +SRCS = example.c +INTERFACE = example.i +LUA_INTERP = embed2.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 + diff --git a/Examples/lua/embed2/embed2.c b/Examples/lua/embed2/embed2.c new file mode 100644 index 000000000..12c81735e --- /dev/null +++ b/Examples/lua/embed2/embed2.c @@ -0,0 +1,221 @@ +/* embed2.c some more test for an embeded interpreter + +This will go a bit further as it will pass values to and from the lua code. +It uses less of the SWIG code, and more of the raw lua API's + +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 +#include + +#include +#include +#include +#include + + +/* the SWIG wrappered library */ +extern int luaopen_example(lua_State*L); + +/* This is an example of how to call the Lua function + int add(int,int) + its very tedious, but gives you an idea of the issues involded. + (look below for a better idea) +*/ +int call_add(lua_State *L,int a,int b,int* res) { + int top; + /* ok, here we go: + push a, push b, call 'add' check & return res + */ + top=lua_gettop(L); /* for later */ + lua_pushstring(L, "add"); /* function name */ + lua_gettable(L, LUA_GLOBALSINDEX); /* function to be called */ + if (!lua_isfunction(L,-1)) { + printf("[C] error: cannot find function 'add'\n"); + lua_settop(L,top); // reset + return 0; + } + lua_pushnumber(L,a); + lua_pushnumber(L,b); + if (lua_pcall(L, 2, 1, 0) != 0) /* call function with 2 arguments and 1 result */ + { + printf("[C] error running function `add': %s\n",lua_tostring(L, -1)); + lua_settop(L,top); // reset + return 0; + } + // check results + if (!lua_isnumber(L,-1)) { + printf("[C] error: returned value is not a number\n"); + lua_settop(L,top); // reset + return 0; + } + *res=(int)lua_tonumber(L,-1); + lua_settop(L,top); /* reset stack */ + return 1; // ok +} + +/* This is a variargs call function for calling from C into Lua. +Original Code from Programming in Lua (PIL) by Roberto Ierusalimschy +ISBN 85-903798-1-7 +http://www.lua.org/pil/25.3.html +This has been modified slightly to make it compile, and its still a bit rough. +But it gives the idea of how to make it work. +*/ +int call_va (lua_State *L,const char *func, const char *sig, ...) { + va_list vl; + int narg, nres; /* number of arguments and results */ + int top; + top=lua_gettop(L); /* for later */ + + va_start(vl, sig); + lua_getglobal(L, func); /* get function */ + + /* push arguments */ + narg = 0; + while (*sig) { /* push arguments */ + switch (*sig++) { + + case 'd': /* double argument */ + lua_pushnumber(L, va_arg(vl, double)); + break; + + case 'i': /* int argument */ + lua_pushnumber(L, va_arg(vl, int)); + break; + + case 's': /* string argument */ + lua_pushstring(L, va_arg(vl, char *)); + break; + + case '>': + goto endwhile; + + default: + printf("invalid option (%c)\n", *(sig - 1)); + goto fail; + } + narg++; + /* do we need this?*/ + /* luaL_checkstack(L, 1, "too many arguments"); */ + } +endwhile: + + /* do the call */ + nres = strlen(sig); /* number of expected results */ + if (lua_pcall(L, narg, nres, 0) != 0) /* do the call */ + { + printf("error running function `%s': %s\n",func, lua_tostring(L, -1)); + goto fail; + } + + /* retrieve results */ + nres = -nres; /* stack index of first result */ + while (*sig) { /* get results */ + switch (*sig++) { + + case 'd': /* double result */ + if (!lua_isnumber(L, nres)) { + printf("wrong result type\n"); + goto fail; + } + *va_arg(vl, double *) = lua_tonumber(L, nres); + break; + + case 'i': /* int result */ + if (!lua_isnumber(L, nres)) { + printf("wrong result type\n"); + goto fail; + } + *va_arg(vl, int *) = (int)lua_tonumber(L, nres); + break; + + case 's': /* string result */ + if (!lua_isstring(L, nres)) { + printf("wrong result type\n"); + goto fail; + } + strcpy(va_arg(vl, char *),lua_tostring(L, nres));/* WARNING possible buffer overflow */ + break; + + default: { + printf("invalid option (%c)", *(sig - 1)); + goto fail; + } + } + nres++; + } + va_end(vl); + + lua_settop(L,top); /* reset stack */ + return 1; /* ok */ +fail: + lua_settop(L,top); /* reset stack */ + return 0; /* error */ +} + +int main(int argc,char* argv[]) { + lua_State *L; + int ok; + int res; + char str[80]; + 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 Lua function 'add(1,1)'\n"); + printf("[C] using the C function 'call_add'\n"); + ok=call_add(L,1,1,&res); + printf("[C] the function returned %d with value %d\n",ok,res); + printf("\n"); + printf("[C] lets do this rather easier\n"); + printf("[C] we will call the same Lua function using a generic C function 'call_va'\n"); + ok=call_va(L,"add","ii>i",1,1,&res); + printf("[C] the function returned %d with value %d\n",ok,res); + printf("\n"); + printf("[C] we will now use the same generic C function to call 'append(\"cat\",\"dog\")'\n"); + ok=call_va(L,"append","ss>s","cat","dog",str); + printf("[C] the function returned %d with value %s\n",ok,str); + printf("\n"); + printf("[C] we can also make some bad calls to ensure the code doesn't fail\n"); + printf("[C] calling adds(1,2)\n"); + ok=call_va(L,"adds","ii>i",1,2,&res); + printf("[C] the function returned %d with value %d\n",ok,res); + printf("[C] calling add(1,'fred')\n"); + ok=call_va(L,"add","is>i",1,"fred",&res); + printf("[C] the function returned %d with value %d\n",ok,res); + printf("\n"); + printf("[C] Note: no protection if you mess up the va-args, this is C\n"); + printf("\n"); + printf("[C] Finally we will call the wrappered gcd function gdc(6,9):\n"); + printf("[C] This will pass the values to Lua, then call the wrappered function\n"); + printf(" Which will get the values from Lua, call the C code \n"); + printf(" and return the value to Lua and eventually back to C\n"); + printf("[C] Certainly not the best way to do it :-)\n"); + ok=call_va(L,"gcd","ii>i",6,9,&res); + printf("[C] the function returned %d with value %d\n",ok,res); + printf("\n"); + printf("[C] all finished, closing the lua state\n"); + lua_close(L); + return 0; +} diff --git a/Examples/lua/embed2/example.c b/Examples/lua/embed2/example.c new file mode 100644 index 000000000..c6c6d7ba1 --- /dev/null +++ b/Examples/lua/embed2/example.c @@ -0,0 +1,22 @@ +/* File : example.c */ + +#include + +/* 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"); +} diff --git a/Examples/lua/embed2/example.i b/Examples/lua/embed2/example.i new file mode 100644 index 000000000..7784b8e3c --- /dev/null +++ b/Examples/lua/embed2/example.i @@ -0,0 +1,8 @@ +/* File : example.i */ +%module example + +%inline %{ +extern int gcd(int x, int y); +extern double Foo; +extern void greeting(); +%} \ No newline at end of file diff --git a/Examples/lua/embed2/runme.lua b/Examples/lua/embed2/runme.lua new file mode 100644 index 000000000..73af9c5f2 --- /dev/null +++ b/Examples/lua/embed2/runme.lua @@ -0,0 +1,27 @@ +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") + +-- note: we will copy the functions from example table into global +-- this will help us later +for k,v in pairs(example) do _G[k]=v end + +-- our add function +-- we will be calling this from C +function add(a,b) + print("[lua] this is function add(",a,b,")") + c=a+b + print("[lua] returning",c) + return c +end + +function append(a,b) + print("[lua] this is function append(",a,b,")") + c=a..b + print("[lua] returning",c) + return c +end + + diff --git a/Examples/lua/exception/Makefile b/Examples/lua/exception/Makefile new file mode 100644 index 000000000..8657f1922 --- /dev/null +++ b/Examples/lua/exception/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = +TARGET = example +INTERFACE = example.i +LIBS = -lm + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' lua_cpp + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mylua' INTERFACE='$(INTERFACE)' lua_cpp_static + +clean:: + $(MAKE) -f $(TOP)/Makefile lua_clean + +check: all diff --git a/Examples/lua/exception/example.h b/Examples/lua/exception/example.h new file mode 100644 index 000000000..5148a5962 --- /dev/null +++ b/Examples/lua/exception/example.h @@ -0,0 +1,53 @@ +/* File : example.h */ + +#include +#ifndef SWIG +struct A { +}; +#endif + +class Exc { +public: + Exc(int c, const char *m) { + code = c; + strncpy(msg,m,256); + } + int code; + char msg[256]; +}; + +#if defined(_MSC_VER) + #pragma warning(disable: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) +#endif + +class Test { +public: + int simple() throw(int&) { + throw(37); + return 1; + } + int message() throw(const char *) { + throw("I died."); + return 1; + } + int hosed() throw(Exc) { + throw(Exc(42,"Hosed")); + return 1; + } + int unknown() throw(A*) { + static A a; + throw &a; + return 1; + } + int multi(int x) throw(int, const char *, Exc) { + if (x == 1) throw(37); + if (x == 2) throw("Bleah!"); + if (x == 3) throw(Exc(42,"No-go-diggy-die")); + return 1; + } +}; + +#if defined(_MSC_VER) + #pragma warning(default: 4290) // C++ exception specification ignored except to indicate a function is not __declspec(nothrow) +#endif + diff --git a/Examples/lua/exception/example.i b/Examples/lua/exception/example.i new file mode 100644 index 000000000..09cd9e812 --- /dev/null +++ b/Examples/lua/exception/example.i @@ -0,0 +1,17 @@ +/* File : example.i */ +%module example + +%{ +#include "example.h" +%} + +%include "std_string.i" + +// we want to return Exc objects to the interpreter +// therefore we add this typemap +// note: only works if Exc is copyable +%apply SWIGTYPE EXCEPTION_BY_VAL {Exc}; + +/* Let's just grab the original header file here */ +%include "example.h" + diff --git a/Examples/lua/exception/runme.lua b/Examples/lua/exception/runme.lua new file mode 100644 index 000000000..63299888e --- /dev/null +++ b/Examples/lua/exception/runme.lua @@ -0,0 +1,63 @@ +-- file: example.lua + +---- 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','luaopen_example') or loadlib('example.so','luaopen_example') + assert(lib)() +else + -- lua 5.1 does + require('example') +end + +-- throw a lot of exceptions: +-- you must catch exceptions using pcall and then checking the result + +t = example.Test() + +print "calling t:unknown()" +ok,res=pcall(function() t:unknown() end) +if ok then + print " that worked! Funny" +else + print(" call failed with error:",res) +end + +print "calling t:simple()" +ok,res=pcall(function() t:simple() end) +if ok then + print " that worked! Funny" +else + print(" call failed with error:",res) +end + +print "calling t:message()" +ok,res=pcall(function() t:message() end) +if ok then + print " that worked! Funny" +else + print(" call failed with error:",res) +end + +print "calling t:hosed()" +ok,res=pcall(function() t:hosed() end) +if ok then + print " that worked! Funny" +else + print(" call failed with error:",res.code,res.msg) +end + +-- this is a rather strange way to perform the multiple catch of exceptions +print "calling t:mutli()" +for i=1,3 do + ok,res=pcall(function() t:multi(i) end) + if ok then + print " that worked! Funny" + else + if swig_type(res)=="Exc *" then + print(" call failed with Exc exception:",res.code,res.msg) + else + print(" call failed with error:",res) + end + end +end -- cgit v1.2.1