[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
This commit is contained in:
Mark Gossage 2008-03-06 09:44:48 +00:00
commit 8350c724f5
18 changed files with 749 additions and 149 deletions

View file

@ -3,6 +3,8 @@ class
constants
dual
embed
embed2
exception
funcptr3
functest
functor

View file

@ -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 <stdlib.h>
#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;
}
/* 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 <stdlib.h>
#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;
}

View file

@ -1,23 +1,22 @@
/* File : example.c */
#include <stdio.h>
/* 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 <stdio.h>
/* 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");
}

View file

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

View file

@ -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 <stdlib.h>
#include <stdio.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdarg.h>
/* 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;
}

View file

@ -0,0 +1,22 @@
/* File : example.c */
#include <stdio.h>
/* 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");
}

View file

@ -0,0 +1,8 @@
/* File : example.i */
%module example
%inline %{
extern int gcd(int x, int y);
extern double Foo;
extern void greeting();
%}

View file

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

View file

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

View file

@ -0,0 +1,53 @@
/* File : example.h */
#include <string>
#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

View file

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

View file

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