Support for Lua added - patch from Mark Gossage

git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@7364 626c5289-ae23-0410-ae9c-e8d60b6d4f22
This commit is contained in:
William S Fulton 2005-08-15 20:44:08 +00:00
commit e2c90c74a9
3 changed files with 1623 additions and 0 deletions

452
SWIG/Lib/lua/lua.swg Normal file
View file

@ -0,0 +1,452 @@
/***********************************************************************
* lua.swg
*
* SWIG Configuration File for Lua
* This file is parsed by SWIG before reading any other interface
* file.
*
* Author : Mark Gossage (mark@gossage.cjb.net)
************************************************************************/
/* -----------------------------------------------------------------------------
* includes
* ----------------------------------------------------------------------------- */
%runtime "swigrun.swg"; /* Common C API type-checking code */
%runtime "luarun.swg"; /* Lua runtime stuff */
/* -----------------------------------------------------------------------------
* standard typemaps
* ----------------------------------------------------------------------------- */
/* NEW LANGUAGE NOTE:
the 'checkfn' param is something that I added for typemap(in)
it is an optional fn call to check the type of the lua object
the fn call must be of the form
int checkfn(lua_State *L, int index);
and return 1/0 depending upon if this is the correct type
For the typemap(out), an additional SWIG_arg parmeter must be incremented
to reflect the number of values returned (normally SWIG_arg++; will do)
*/
// numbers
%typemap(in,checkfn="lua_isnumber") int,short,long,
unsigned int,unsigned short,unsigned long,
signed char,unsigned char,
float,double,enum SWIGTYPE
%{$1 = ($type)lua_tonumber(L, $input);%}
%typemap(out) int,short,long,
unsigned int,unsigned short,unsigned long,
signed char,unsigned char,
float,double,enum SWIGTYPE
%{ lua_pushnumber(L, (double) $1); SWIG_arg++;%}
// boolean (which is a special type in lua)
// note: 1 & 0 are not booleans in lua, only true & false
%typemap(in,checkfn="lua_isboolean") bool
%{$1 = (bool)lua_toboolean(L, $input);%}
%typemap(out) bool, const bool&
%{ lua_pushboolean(L,(int)$1); SWIG_arg++;%}
// for const bool&, SWIG treats this as a const bool* so we must dereference it
%typemap(in,checkfn="lua_isboolean") const bool& (bool temp)
%{temp=(bool)lua_toboolean(L, $input); $1=&temp;%}
%typemap(out) const bool&
%{ lua_pushboolean(L,(int)*$1); SWIG_arg++;%}
// strings (char* and char[])
%typemap(in,checkfn="lua_isstring") const char*, char*, const char[ANY], char[ANY]
%{$1 = (char*)lua_tostring(L, $input);%}
%typemap(out) const char*, char*, const char[ANY], char[ANY]
%{ lua_pushstring(L,$1); SWIG_arg++;%}
// char's
// currently treating chars as small strings, not as numbers
// (however signed & unsigned char's are numbers...)
%typemap(in,checkfn="lua_isstring") char
%{$1 = ((char*)lua_tostring(L, $input))[0];%}
%typemap(out) char
%{ lua_pushfstring(L,"%c",$1); SWIG_arg++;%}
// byref
%typemap(in,checkfn="lua_isstring") const char& (char temp)
%{temp = ((char*)lua_tostring(L, $input))[0]; $1=&temp;%}
%typemap(out) const char&
%{ lua_pushfstring(L,"%c",*$1); SWIG_arg++;%}
// pointers and references
%typemap(in,checkfn="lua_isuserdata") SWIGTYPE*,SWIGTYPE&,SWIGTYPE[]
//%{if(SWIG_ConvertPtr(L,$input,(void**)(&$1),$descriptor,SWIG_POINTER_EXCEPTION) == -1) SWIG_fail; %}
%{$1=($1_ltype)SWIG_MustGetPtr(L,$input,$descriptor,0,$argnum,"$symname");%}
%typemap(out) SWIGTYPE*,SWIGTYPE&
%{SWIG_NewPointerObj(L,$1,$descriptor,$owner); SWIG_arg++; %}
// passing objects by value (yuk: do you really have to do this?)
// what we do is get it as a pointer (the $&ltype argp)
// then do an assignment
%typemap(in,checkfn="lua_isuserdata") SWIGTYPE
{
$&ltype argp;
if(SWIG_ConvertPtr(L,$input,(void**)(&argp),$&descriptor,SWIG_POINTER_EXCEPTION) == -1) SWIG_fail;
$1 = *argp;
}
// Primitive types--return by value
// must make a new object, copy the data & return the new object
#ifdef __cplusplus
%typemap(out) SWIGTYPE
{
$&1_ltype resultptr;
resultptr = new $1_ltype(($1_ltype &) $1);
SWIG_NewPointerObj(L,(void *) resultptr,$&1_descriptor,1); SWIG_arg++;
}
#else
%typemap(out) SWIGTYPE
{
$&1_ltype resultptr;
resultptr = ($&1_ltype) malloc(sizeof($1_type));
memmove(resultptr, &$1, sizeof($1_type));
SWIG_NewPointerObj(L,(void *) resultptr,$&1_descriptor,1); SWIG_arg++;
}
#endif
// void (must be empty without the SWIG_arg++)
%typemap(out) void "";
/* -----------------------------------------------------------------------------
* constants typemaps
* ----------------------------------------------------------------------------- */
// this basically adds to a table of constants
%typemap(consttab) int, unsigned int, short, unsigned short, long, unsigned long, unsigned char, signed char, bool, enum SWIGTYPE
{ SWIG_LUA_INT, (char *)"$symname", (long) $value, 0, 0, 0}
%typemap(consttab) float, double
{ SWIG_LUA_FLOAT, (char *)"$symname", 0, (double) $value, 0, 0}
%typemap(consttab) char, char *
{ SWIG_LUA_STRING, (char *)"$symname", 0, 0, (void *)"$value", 0}
%typemap(consttab) long long, unsigned long long
{ SWIG_LUA_STRING, (char *) "$symname", 0, 0, (void *)"$value", 0}
%typemap(consttab) SWIGTYPE *, SWIGTYPE &, SWIGTYPE []
{ SWIG_LUA_POINTER, (char *)"$symname", 0, 0, (void *)$value, &$1_descriptor}
// TODO: not complete
//%typemap(consttab) SWIGTYPE (CLASS::*)
// { SWIG_LUA_BINARY, (char *)"$symname", sizeof($type), 0, (void *)&$value, &$1_descriptor}
/* -----------------------------------------------------------------------------
* typecheck rules
* ----------------------------------------------------------------------------- */
/* These are needed for the overloaded functions
These define the detection routines which will spot what
parmeters match which function
*/
// unfortunately lua only considers one type of number
// so all numbers (int,float,double) match
// you could add an advanced fn to get type & check if its integral
%typecheck(SWIG_TYPECHECK_INTEGER)
int, short, long,
unsigned int, unsigned short, unsigned long,
signed char, unsigned char,
long long, unsigned long long,
const int &, const short &, const long &,
const unsigned int &, const unsigned short &, const unsigned long &,
const long long &, const unsigned long long &,
enum SWIGTYPE, float, double,
const float &, const double &
{
$1 = lua_isnumber(L,$input);
}
%typecheck(SWIG_TYPECHECK_BOOL)
bool, const bool &
{
$1 = lua_isboolean(L,$input);
}
// special check for a char (string of length 1)
%typecheck(SWIG_TYPECHECK_CHAR) char {
$1 = lua_isstring(L,$input) && (lua_strlen(L,$input)==1);
}
%typecheck(SWIG_TYPECHECK_STRING) char * {
$1 = lua_isstring(L,$input);
}
%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] {
void *ptr;
if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $1_descriptor, 0)) {
$1 = 0;
} else {
$1 = 1;
}
}
%typecheck(SWIG_TYPECHECK_VOIDPTR) void * {
void *ptr;
if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, 0, 0)) {
$1 = 0;
} else {
$1 = 1;
}
}
/* -----------------------------------------------------------------------------
* Const reference issues
* ----------------------------------------------------------------------------- */
// additional typemaps for privitives by const reference:
// given a function:
// int intbyref(const int& i);
// SWIG assumes that this code will need a pointer to int to be passed in
// (this might be ok for passing objects by const ref, but not a primitive)
// therefore we add a set of blanket typemaps to fix this
// also a set for fns which return const X&
// %typemap(in,checkfn="lua_isnumber") const int &(int temp)
// %{ temp = (int)lua_tonumber(L,$input); $1=&temp;%}
// %typemap(out) const int&
// %{ lua_pushnumber(L, (double) $*1); SWIG_arg++;%}
// %typecheck(in,checkfn="lua_isnumber") const int &
// now the code
%define SWIG_NUMBER_BY_CONST_REF(TYPE)
%typemap(in,checkfn="lua_isnumber") const TYPE &($basetype temp)
%{ temp=($basetype)lua_tonumber(L,$input); $1=&temp;%}
%typemap(out) const TYPE&
%{ lua_pushnumber(L, (double) *$1); SWIG_arg++;%}
%enddef
SWIG_NUMBER_BY_CONST_REF(int);
SWIG_NUMBER_BY_CONST_REF(unsigned int);
SWIG_NUMBER_BY_CONST_REF(signed int);
SWIG_NUMBER_BY_CONST_REF(short);
SWIG_NUMBER_BY_CONST_REF(unsigned short);
SWIG_NUMBER_BY_CONST_REF(signed short);
SWIG_NUMBER_BY_CONST_REF(long);
SWIG_NUMBER_BY_CONST_REF(unsigned long);
SWIG_NUMBER_BY_CONST_REF(signed long);
//SWIG_NUMBER_BY_CONST_REF(char); // char's are now small strings
SWIG_NUMBER_BY_CONST_REF(unsigned char);
SWIG_NUMBER_BY_CONST_REF(signed char);
SWIG_NUMBER_BY_CONST_REF(float);
SWIG_NUMBER_BY_CONST_REF(double);
SWIG_NUMBER_BY_CONST_REF(enum SWIGTYPE);
// Also needed for object ptrs by const ref
// eg const A* ref_pointer(A* const& a);
// found in mixed_types.i
%typemap(in,checkfn="lua_isuserdata") SWIGTYPE* const &($*ltype temp)
%{temp=($*ltype)SWIG_MustGetPtr(L,$input,$*descriptor,0,$argnum,"$symname");
$1=&temp;%}
// and the pytcheck code
%typecheck(SWIG_TYPECHECK_POINTER) SWIGTYPE* const &
%{
void *ptr;
if (lua_isuserdata(L,$input)==0 || SWIG_ConvertPtr(L,$input, (void **) &ptr, $*descriptor, 0)) {
$1 = 0;
} else {
$1 = 1;
}
%}
/* -----------------------------------------------------------------------------
* Overloaded operator support
* ----------------------------------------------------------------------------- */
// lua likes to call the + operator '__add'
// python likes to call it '__add__'
// Assuming most SWIGers will probably use the __add__ if they extend their classes
// we have two sets of renames
// one to rename the operator+() to __add()
// (this lets SWIG rename the operator overloads)
// another is to rename __add__() to __add()
// (this means that people who wrote SWIG code to do that add will also work)
#ifdef __cplusplus
// this is extra renaming for lua
// not all operators are supported, so only those that are, are listed
/* Ignored operators */
%ignorewarn("362:operator= ignored") operator=;
%ignorewarn("362:operator% ignored") operator%;
%ignorewarn("383:operator++ ignored") operator++;
%ignorewarn("384:operator-- ignored") operator--;
%ignorewarn("361:operator! ignored") operator!;
%ignorewarn("381:operator&& ignored") operator&&;
%ignorewarn("382:operator|| ignored") operator||;
%ignorewarn("386:operator->* ignored") operator->*;
%ignorewarn("362:operator+= ignored") operator+=;
%ignorewarn("362:operator-= ignored") operator-=;
%ignorewarn("362:operator*= ignored") operator*=;
%ignorewarn("362:operator/= ignored") operator/=;
%ignorewarn("362:operator%= ignored") operator%=;
%ignorewarn("389:operator[] ignored (consider using %extend)") operator[];
// renaming the main C++ operators
%rename(__add) *::operator+;
%rename(__sub) *::operator-;
%rename(__mul) *::operator*;
%rename(__div) *::operator/;
%rename(__unm) *::operator-();
%rename(__unm) *::operator-() const;
%rename(__eq) *::operator==; // note: Lua does not have a not equal
// it just uses 'not (a==b)'
%ignore *::operator!=;
%rename(__lt) *::operator<; // ditto less than vs greater than
%ignore *::operator>;
%rename(__le) *::operator<=; // ditto less than vs greater than
%ignore *::operator>=;
%rename(__call) *::operator(); // the fn call operator
// renaming the python operators to be compatible with lua
// this means that if a developer has written a fn __add__()
// it will be used for the lua +
%rename(__add) *::__add__;
%rename(__sub) *::__sub__;
%rename(__mul) *::__mul__;
%rename(__div) *::__div__;
%rename(__unm) *::__neg__; // lua calls unary minus,'unm' not 'neg'
%rename(__tostring) *::__str__; // both map to __tostring
%rename(__tostring) *::__repr__; // both map to __tostring
%rename(__pow) *::__pow__; // lua power '^' operator
%rename(__concat) *::__concat__; // lua concat '..' operator
%rename(__eq) *::__eq__;
%rename(__lt) *::__lt__;
%rename(__le) *::__le__;
%rename(__call) *::__call__; // the fn call operator()
// the [] operator has two parts, the get & the set
%rename(__getitem) *::__getitem__; // the v=X[i] (get operator)
%rename(__setitem) *::__setitem__; // the X[i]=v (set operator)
#endif
/* ------------------------------------------------------------
* Exceptions
* ------------------------------------------------------------ */
/* Confession: I dont really like C++ exceptions
The python ones are great, but C++ ones I dont like
(mainly because I cannot get the stack trace out of it)
Therefore I have not bothered to try doing much in this
On top of this I an not clear on how best to do this is Lua
Therefore currently its just enough to get a few test cases running ok
*/
%typemap(throws) int,unsigned int,signed int,
long,unsigned long,signed long,
short,unsigned short,signed short,
bool,float,double,
long long,unsigned long long,
char, unsigned char, signed char,
enum SWIGTYPE
%{lua_pushfstring(L,"exception thrown of value %d",(long)$1);
SWIG_fail; %}
#include "exception.h"
#define SWIG_exception(a,b)\
{ lua_pushfstring(L,"%s thrown:%s",#a,b);SWIG_fail; }
#ifdef __cplusplus
%typemap(throws) SWIGTYPE
{
$&1_ltype resultptr;
resultptr = new $1_ltype(($1_ltype &) $1);
SWIG_NewPointerObj(L,(void *) resultptr,$&1_descriptor,1);
SWIG_fail;
}
#else
%typemap(throws) SWIGTYPE
{
$&1_ltype resultptr;
resultptr = ($&1_ltype) malloc(sizeof($1_type));
memmove(resultptr, &$1, sizeof($1_type));
SWIG_NewPointerObj(L,(void *) resultptr,$&1_descriptor,1);
SWIG_fail;
}
#endif
/* ------------------------------------------------------------
* SWIG_init
* ------------------------------------------------------------ */
%insert(init) "swiginit.swg"
// 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
%init %{
#ifdef __cplusplus
extern "C"
#endif
SWIGEXPORT int SWIG_init(lua_State* L)
{
int i;
// start with global table
lua_pushvalue(L,LUA_GLOBALSINDEX);
SWIG_InitializeModule((void*)L);
SWIG_PropagateClientData();
// 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].wrapper);
}
// 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);
// end module
SWIG_Lua_module_end(L);
lua_pop(L,1); // tidy stack (remove global table)
return 1;
}
%}
/* Note: the initialization function is closed after all code is generated */
/*************************** end lua.swg ******************************/

681
SWIG/Lib/lua/luarun.swg Normal file
View file

@ -0,0 +1,681 @@
/***********************************************************************
* luarun.swg
*
* This file contains the runtime support for Lua modules
* and includes code for managing global variables and pointer
* type checking.
*
* Author : Mark Gossage (mark@gossage.cjb.net)
************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
#include "lua.h"
#include "stdio.h" // debug printing
#include <assert.h> // for a few sanity tests
/* -----------------------------------------------------------------------------
* global swig types
* ----------------------------------------------------------------------------- */
/* Constant table */
#define SWIG_LUA_INT 1
#define SWIG_LUA_FLOAT 2
#define SWIG_LUA_STRING 3
#define SWIG_LUA_POINTER 4
#define SWIG_LUA_BINARY 5
/* Flags for pointer conversion */
#define SWIG_POINTER_EXCEPTION 0x1
/* type for all wrapper fns */
typedef int (*swig_lua_wrapper_func)(lua_State*);
/* Structure for command table */
typedef struct {
const char *name;
swig_lua_wrapper_func wrapper;
} swig_lua_command_info;
/* Structure for variable linking table */
typedef struct {
const char *name;
swig_lua_wrapper_func get;
swig_lua_wrapper_func set;
} swig_lua_var_info;
/* Constant information structure */
typedef struct {
int type;
char *name;
long lvalue;
double dvalue;
void *pvalue;
swig_type_info **ptype;
} swig_lua_const_info;
typedef struct {
const char *name;
swig_lua_wrapper_func method;
} swig_lua_method;
typedef struct {
const char *name;
swig_lua_wrapper_func getmethod;
swig_lua_wrapper_func setmethod;
} swig_lua_attribute;
typedef struct swig_lua_class {
const char *name;
swig_type_info **type;
swig_lua_wrapper_func constructor;
void (*destructor)(void *);
swig_lua_method *methods;
swig_lua_attribute *attributes;
struct swig_lua_class **bases;
} swig_lua_class;
typedef struct {
void *ptr;
swig_type_info *type;
int own; // 1 if owned & must be destroyed
} swig_lua_userdata;
/* Common SWIG API */
#define SWIG_NewPointerObj(L, ptr, type, owner) \
SWIG_Lua_NewPointerObj(L, (void *)ptr, type, owner)
#define SWIG_ConvertPtr(L,idx, ptr, type, flags) \
SWIG_Lua_ConvertPtr(L,idx,ptr,type,flags)
#define SWIG_MustGetPtr(L,idx, type,flags, argnum,fnname) \
SWIG_Lua_MustGetPtr(L,idx, type,flags, argnum,fnname)
/* Runtime API */
#define SWIG_GetModule(clientdata) SWIG_Lua_GetModule((lua_State*)(clientdata))
#define SWIG_SetModule(clientdata, pointer) SWIG_Lua_SetModule((lua_State*) (clientdata), pointer)
#define SWIG_MODULE_CLIENTDATA_TYPE lua_State*
/* Contract support */
#define SWIG_contract_assert(expr, msg) \
if (!(expr)) { lua_pushstring(L, (char *) msg); goto fail; } else
// helper #defines
#define SWIG_fail {goto fail;}
#define SWIG_fail_arg(I) {lua_pushfstring(L,"argument %d incorrect/missing",I);goto fail;}
#define SWIG_Lua_get_table(L,n) \
(lua_pushstring(L, n), lua_rawget(L,-2))
#define SWIG_Lua_add_function(L,n,f) \
(lua_pushstring(L, n), \
lua_pushcfunction(L, f), \
lua_rawset(L,-3))
// debug routine
#if 0
#define DEBUG_PRINT(X) {printf(X);fflush(stdout);}
#define DEBUG_STACK(X) {swig_print_stack(L);}
void swig_print_stack(lua_State* L)
{
int i=lua_gettop(L);
printf("stack is size %d==============\n",i);
for( ; i>0;i--)
printf(" %d %p(%s)\n",i,lua_topointer(L,i),lua_typename(L,lua_type(L,i)));
printf("end stack==============\n");
fflush(stdout);
}
#else
#define DEBUG_PRINT(X) {}
#define DEBUG_STACK(X) {}
#endif
/* -----------------------------------------------------------------------------
* global variable support code: modules
* ----------------------------------------------------------------------------- */
// the module.get method used for getting linked data
SWIGINTERN int SWIG_Lua_module_get(lua_State* L)
{
// there should be 2 params passed in
// (1) table (not the meta table)
// (2) string name of the attribute
// printf("SWIG_Lua_module_get %p(%s) '%s'\n",
// lua_topointer(L,1),lua_typename(L,lua_type(L,1)),
// lua_tostring(L,2));
// get the metatable
assert(lua_istable(L,1)); // just in case
lua_getmetatable(L,1); // get the metatable
assert(lua_istable(L,-1)); // just in case
SWIG_Lua_get_table(L,".get"); // get the .get table
lua_remove(L,3); // remove metatable
// printf(" found %p(%s)\n",lua_topointer(L,-1),lua_typename(L,lua_type(L,-1)));
if (lua_istable(L,-1))
{
// look for the key in the .get table
lua_pushvalue(L,2); // key
lua_rawget(L,-2);
lua_remove(L,3); // remove .get
if (lua_iscfunction(L,-1))
{ // found it so call the fn & return its value
// printf("calling fn\n");
lua_call(L,0,1);
return 1;
}
lua_pop(L,1); // remove the top
}
lua_pop(L,1); // remove the .get
lua_pushnil(L); // return a nil
return 1;
}
// the module.set method used for setting linked data
SWIGINTERN int SWIG_Lua_module_set(lua_State* L)
{
// there should be 3 params passed in
// (1) table (not the meta table)
// (2) string name of the attribute
// (3) any for the new value
// printf("SWIG_Lua_module_set %p(%s) '%s' %p(%s)\n",
// lua_topointer(L,1),lua_typename(L,lua_type(L,1)),
// lua_tostring(L,2),
// lua_topointer(L,3),lua_typename(L,lua_type(L,3)));
// get the metatable
assert(lua_istable(L,1)); // just in case
lua_getmetatable(L,1); // get the metatable
assert(lua_istable(L,-1)); // just in case
SWIG_Lua_get_table(L,".set"); // get the .set table
lua_remove(L,4); // remove metatable
if (lua_istable(L,-1))
{
// look for the key in the .set table
lua_pushvalue(L,2); // key
lua_rawget(L,-2);
lua_remove(L,4); // remove .set
if (lua_iscfunction(L,-1))
{ // found it so call the fn & return its value
lua_pushvalue(L,3); // value
lua_call(L,1,0);
return 0;
}
lua_pop(L,1); // remove the top
}
lua_pop(L,1); // remove the .set
return 0;
}
// registering a module in lua
SWIGINTERN void SWIG_Lua_module_begin(lua_State* L,const char* name)
{
assert(lua_istable(L,-1)); // just in case
lua_pushstring(L,name);
lua_newtable(L); // the table
// add meta table
lua_newtable(L); // the meta table
SWIG_Lua_add_function(L,"__index",SWIG_Lua_module_get);
SWIG_Lua_add_function(L,"__newindex",SWIG_Lua_module_set);
lua_pushstring(L,".get");
lua_newtable(L); // the .get table
lua_rawset(L,-3); // add .get into metatable
lua_pushstring(L,".set");
lua_newtable(L); // the .set table
lua_rawset(L,-3); // add .set into metatable
lua_setmetatable(L,-2); // sets meta table in module
lua_rawset(L,-3); // add module into parent
SWIG_Lua_get_table(L,name); // get the table back out
}
// ending the register
SWIGINTERN void SWIG_Lua_module_end(lua_State* L)
{
lua_pop(L,1); // tidy stack (remove module)
}
// adding a linked variable to the module
SWIGINTERN void SWIG_Lua_module_add_variable(lua_State* L,const char* name,swig_lua_wrapper_func getFn,swig_lua_wrapper_func setFn)
{
assert(lua_istable(L,-1)); // just in case
lua_getmetatable(L,-1); // get the metatable
assert(lua_istable(L,-1)); // just in case
SWIG_Lua_get_table(L,".get"); // find the .get table
assert(lua_istable(L,-1)); // should be a table:
SWIG_Lua_add_function(L,name,getFn);
lua_pop(L,1); // tidy stack (remove table)
if (setFn) // if there is a set fn
{
SWIG_Lua_get_table(L,".set"); // find the .set table
assert(lua_istable(L,-1)); // should be a table:
SWIG_Lua_add_function(L,name,setFn);
lua_pop(L,1); // tidy stack (remove table)
}
lua_pop(L,1); // tidy stack (remove meta)
}
// adding a function module
SWIGINTERN void SWIG_Lua_module_add_function(lua_State* L,const char* name,swig_lua_wrapper_func fn)
{
SWIG_Lua_add_function(L,name,fn);
}
/* -----------------------------------------------------------------------------
* global variable support code: classes
* ----------------------------------------------------------------------------- */
// the class.get method, performs the lookup of class attributes
SWIGINTERN int SWIG_Lua_class_get(lua_State* L)
{
// there should be 2 params passed in
// (1) userdata (not the meta table)
// (2) string name of the attribute
// printf("SWIG_Lua_class_get %p(%s) '%s'\n",
// lua_topointer(L,1),lua_typename(L,lua_type(L,1)),
// lua_tostring(L,2));
// DEBUG_STACK(L);
assert(lua_isuserdata(L,-2)); // just in case
lua_getmetatable(L,-2); // get the meta table
assert(lua_istable(L,-1)); // just in case
SWIG_Lua_get_table(L,".get"); // find the .get table
assert(lua_istable(L,-1)); // just in case
// look for the key in the .get table
lua_pushvalue(L,2); // key
lua_rawget(L,-2);
lua_remove(L,-2); // stack tidy, remove .get table
DEBUG_PRINT("check .get\n");
DEBUG_STACK(L);
if (lua_iscfunction(L,-1))
{ // found it so call the fn & return its value
lua_pushvalue(L,1); // the userdata
lua_call(L,1,1); // 1 value in (userdata),1 out (result)
lua_remove(L,-2); // stack tidy, remove metatable
return 1;
}
lua_pop(L,1); // remove whatever was there
// ok, so try the .fn table
SWIG_Lua_get_table(L,".fn"); // find the .get table
assert(lua_istable(L,-1)); // just in case
lua_pushvalue(L,2); // key
lua_rawget(L,-2); // look for the fn
lua_remove(L,-2); // stack tidy, remove .fn table
DEBUG_PRINT("check .fn\n");
DEBUG_STACK(L);
if (lua_iscfunction(L,-1))
{ // found it so return the fn & let lua call it
lua_remove(L,-2); // stack tidy, remove metatable
return 1;
}
lua_pop(L,1); // remove whatever was there
// NEW: looks for the __getitem() fn
// this is a user provided get fn
SWIG_Lua_get_table(L,"__getitem"); // find the __getitem fn
DEBUG_PRINT("check __getitem\n");
DEBUG_STACK(L);
if (lua_iscfunction(L,-1)) // if its there
{ // found it so call the fn & return its value
lua_pushvalue(L,1); // the userdata
lua_pushvalue(L,2); // the parameter
lua_call(L,2,1); // 2 value in (userdata),1 out (result)
lua_remove(L,-2); // stack tidy, remove metatable
//DEBUG_STACK(L);
return 1;
}
return 0; // sorry not known
}
// the class.set method, performs the lookup of class attributes
SWIGINTERN int SWIG_Lua_class_set(lua_State* L)
{
// there should be 3 params passed in
// (1) table (not the meta table)
// (2) string name of the attribute
// (3) any for the new value
// printf("SWIG_Lua_class_set %p(%s) '%s' %p(%s)\n",
// lua_topointer(L,1),lua_typename(L,lua_type(L,1)),
// lua_tostring(L,2),
// lua_topointer(L,3),lua_typename(L,lua_type(L,3)));
assert(lua_isuserdata(L,1)); // just in case
lua_getmetatable(L,1); // get the meta table
assert(lua_istable(L,-1)); // just in case
SWIG_Lua_get_table(L,".set"); // find the .set table
if (lua_istable(L,-1))
{
// look for the key in the .set table
lua_pushvalue(L,2); // key
lua_rawget(L,-2);
if (lua_iscfunction(L,-1))
{ // found it so call the fn & return its value
lua_pushvalue(L,1); // userdata
lua_pushvalue(L,3); // value
lua_call(L,2,0);
return 0;
}
lua_pop(L,1); // remove the value
}
lua_pop(L,1); // remove the value .set table
// NEW: looks for the __setitem() fn
// this is a user provided set fn
SWIG_Lua_get_table(L,"__setitem"); // find the fn
if (lua_iscfunction(L,-1)) // if its there
{ // found it so call the fn & return its value
lua_pushvalue(L,1); // the userdata
lua_pushvalue(L,2); // the parameter
lua_pushvalue(L,3); // the value
lua_call(L,3,0); // 3 values in ,0 out
lua_remove(L,-2); // stack tidy, remove metatable
return 1;
}
return 0;
}
// the class.destruct method called by the interpreter
SWIGINTERN int SWIG_Lua_class_destruct(lua_State* L)
{
// there should be 1 params passed in
// (1) userdata (not the meta table)
swig_lua_userdata* usr;
swig_lua_class* clss;
// printf("SWIG_Lua_class_destruct\n");
// DEBUG_STACK(L);
assert(lua_isuserdata(L,-1)); // just in case
usr=(swig_lua_userdata*)lua_touserdata(L,-1); // get it
// if must be destroyed & has a destructor
if (usr->own) // if must be destroyed
{
clss=(swig_lua_class*)usr->type->clientdata; // get the class
if (clss && clss->destructor) // there is a destroy fn
{
clss->destructor(usr->ptr); // bye bye
}
}
return 0;
}
// gets the swig class registry (or creates it)
SWIGINTERN void SWIG_Lua_get_class_registry(lua_State* L)
{
// add this all into the swig registry:
lua_pushstring(L,"SWIG");
lua_rawget(L,LUA_REGISTRYINDEX); // get the registry
if (!lua_istable(L,-1)) // not there
{ // must be first time, so add it
lua_pop(L,1); // remove the result
lua_pushstring(L,"SWIG");
lua_newtable(L);
lua_rawset(L,LUA_REGISTRYINDEX);
// then get it
lua_pushstring(L,"SWIG");
lua_rawget(L,LUA_REGISTRYINDEX);
}
}
// helper fn to get the classes metatable from the register
SWIGINTERN void SWIG_Lua_get_class_metatable(lua_State* L,const char* cname)
{
SWIG_Lua_get_class_registry(L); // get the registry
lua_pushstring(L,cname); // get the name
lua_rawget(L,-2); // get it
lua_remove(L,-2); // tidy up (remove registry)
}
// helper add a variable to a registered class
SWIGINTERN void SWIG_Lua_add_class_variable(lua_State* L,const char* name,swig_lua_wrapper_func getFn,swig_lua_wrapper_func setFn)
{
assert(lua_istable(L,-1)); // just in case
SWIG_Lua_get_table(L,".get"); // find the .get table
assert(lua_istable(L,-1)); // just in case
// if (lua_istable(L,-1)) // should be a table:
SWIG_Lua_add_function(L,name,getFn);
lua_pop(L,1); // tidy stack (remove table)
if (setFn)
{
SWIG_Lua_get_table(L,".set"); // find the .set table
assert(lua_istable(L,-1)); // just in case
// if (lua_istable(L,-1)) // should be a table:
SWIG_Lua_add_function(L,name,setFn);
lua_pop(L,1); // tidy stack (remove table)
}
}
// helper to recursively add class details (attributes & operations)
SWIGINTERN void SWIG_Lua_add_class_details(lua_State* L,swig_lua_class* clss)
{
int i;//,j;
// call all the base classes first: we can then override these later:
swig_lua_class* base;
for(i=0;clss->bases[i];i++)
{
// printf("add base class feature %s\n",clss->bases[i]->name); fflush(stdout);
SWIG_Lua_add_class_details(L,clss->bases[i]);
}
// add fns
for(i=0;clss->attributes[i].name;i++){
SWIG_Lua_add_class_variable(L,clss->attributes[i].name,clss->attributes[i].getmethod,clss->attributes[i].setmethod);
}
// add methods to the metatable
SWIG_Lua_get_table(L,".fn"); // find the .fn table
assert(lua_istable(L,-1)); // just in case
for(i=0;clss->methods[i].name;i++){
SWIG_Lua_add_function(L,clss->methods[i].name,clss->methods[i].method);
}
lua_pop(L,1); // tidy stack (remove table)
// add operator overloads
// these look ANY method which start with "__" and assume they
// are operator overloads & add them to the metatable
// (this might mess up is someone defines a method __gc (the destructor)
for(i=0;clss->methods[i].name;i++){
if (clss->methods[i].name[0]=='_' && clss->methods[i].name[1]=='_'){
SWIG_Lua_add_function(L,clss->methods[i].name,clss->methods[i].method);
}
}
}
// performs the entire class registration process
SWIGINTERN void SWIG_Lua_class_register(lua_State* L,swig_lua_class* clss)
{
// add its constructor to module with the name of the class
// so you can do MyClass(...) as well as new_MyClass(...)
// BUT only if a constructor is defined
// (this overcomes the problem of pure virtual classes without constructors)
if (clss->constructor)
SWIG_Lua_add_function(L,clss->name,clss->constructor);
SWIG_Lua_get_class_registry(L); // get the registry
lua_pushstring(L,clss->name); // get the name
lua_newtable(L); // create the metatable
// add string of class name called ".type"
lua_pushstring(L,".type");
lua_pushstring(L,clss->name);
lua_rawset(L,-3);
// add a table called ".get"
lua_pushstring(L,".get");
lua_newtable(L);
lua_rawset(L,-3);
// add a table called ".set"
lua_pushstring(L,".set");
lua_newtable(L);
lua_rawset(L,-3);
// add a table called ".fn"
lua_pushstring(L,".fn");
lua_newtable(L);
lua_rawset(L,-3);
// add accessor fns for using the .get,.set&.fn
SWIG_Lua_add_function(L,"__index",SWIG_Lua_class_get);
SWIG_Lua_add_function(L,"__newindex",SWIG_Lua_class_set);
SWIG_Lua_add_function(L,"__gc",SWIG_Lua_class_destruct);
// add it
lua_rawset(L,-3); // metatable into registry
lua_pop(L,1); // tidy stack (remove registry)
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)
}
/* -----------------------------------------------------------------------------
* Class/structure conversion fns
* ----------------------------------------------------------------------------- */
// pushes a new object into the lua stack
SWIGRUNTIME void SWIG_Lua_NewPointerObj(lua_State* L,void* ptr,swig_type_info *type, int own)
{
if (!ptr){
lua_pushnil(L);
return;
}
swig_lua_userdata* usr=(swig_lua_userdata*)lua_newuserdata(L,sizeof(swig_lua_userdata)); // get data
usr->ptr=ptr; // set the ptr
usr->type=type;
usr->own=own;
// printf("ptr %p type %s class %p\n",ptr,type->name,type->clientdata);
if (type->clientdata) // there is clientdata: so add the metatable
{
SWIG_Lua_get_class_metatable(L,((swig_lua_class*)(type->clientdata))->name);
if (lua_istable(L,-1))
{
// printf("added metatable for %p %s\n",ptr,type->name);
lua_setmetatable(L,-2);
}
else
{
// printf("no metatable for %p %s\n",ptr,type->name);
lua_pop(L,1);
}
}
}
// takes a object from the lua stack & converts it into an object of the correct type
// (if possible)
SWIGRUNTIME int SWIG_Lua_ConvertPtr(lua_State* L,int index,void** ptr,swig_type_info *type,int flags)
{
swig_lua_userdata* usr;
swig_cast_info *cast;
// assert(lua_isuserdata(L,index)); // just in case
usr=(swig_lua_userdata*)lua_touserdata(L,index); // get data
// printf("SWIG_Lua_ConvertPtr(%p,%p) %s %s\n",usr->type,type,usr->type->name,type->name);
if (usr)
{
cast=SWIG_TypeCheckStruct(usr->type,type);
if (cast)
{
*ptr=SWIG_TypeCast(cast,usr->ptr);
return 0; //ok
}
}
return 1; // error
}
SWIGRUNTIME void* SWIG_Lua_MustGetPtr(lua_State* L,int index,swig_type_info *type,int flags,
int argnum,const char* func_name){
void* result;
if (SWIG_ConvertPtr(L,index,&result,type,flags)){
lua_pushfstring(L,"Error in %s, expected a %s at argument number %d\n",
func_name,type->str?type->str:"void*",argnum);
lua_error(L);
}
return result;
}
// lua callable function to get the userdata's type
SWIGRUNTIME int SWIG_Lua_type(lua_State* L)
{
swig_lua_userdata* usr;
if (!lua_isuserdata(L,1)) // just in case
return 0; // nil reply
usr=(swig_lua_userdata*)lua_touserdata(L,1); // get data
lua_pushstring(L,usr->type->name);
return 1;
}
// lua callable function to compare userdata's value
// the issue is that two userdata may point to the same thing
// but to lua, they are different objects
SWIGRUNTIME int SWIG_Lua_equal(lua_State* L)
{
int result;
swig_lua_userdata *usr1,*usr2;
if (!lua_isuserdata(L,1) || !lua_isuserdata(L,2)) // just in case
return 0; // nil reply
usr1=(swig_lua_userdata*)lua_touserdata(L,1); // get data
usr2=(swig_lua_userdata*)lua_touserdata(L,2); // get data
result=(usr1->ptr==usr2->ptr && usr1->type==usr2->type);
lua_pushboolean(L,result);
return 1;
}
/* -----------------------------------------------------------------------------
* global variable support code: class/struct typemap functions
* ----------------------------------------------------------------------------- */
/* Install Constants */
SWIGINTERN void
SWIG_Lua_InstallConstants(lua_State* L, swig_lua_const_info constants[]) {
int i;
for (i = 0; constants[i].type; i++) {
switch(constants[i].type) {
case SWIG_LUA_INT:
lua_pushstring(L,constants[i].name);
lua_pushnumber(L,(double)constants[i].lvalue);
lua_rawset(L,-3);
break;
case SWIG_LUA_FLOAT:
lua_pushstring(L,constants[i].name);
lua_pushnumber(L,(double)constants[i].dvalue);
lua_rawset(L,-3);
break;
case SWIG_LUA_STRING:
lua_pushstring(L,constants[i].name);
lua_pushstring(L,(char *) constants[i].pvalue);
lua_rawset(L,-3);
break;
case SWIG_LUA_POINTER:
lua_pushstring(L,constants[i].name);
SWIG_NewPointerObj(L,constants[i].pvalue, *(constants[i]).ptype,0);
lua_rawset(L,-3);
break;
case SWIG_LUA_BINARY:
// TODO??
// obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype));
break;
default:
//obj = 0;
break;
}
}
}
/* storing/access of swig_module_info */
SWIGRUNTIME swig_module_info *
SWIG_Lua_GetModule(lua_State* L) {
swig_module_info *ret = 0;
lua_pushstring(L,"swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME);
lua_rawget(L,LUA_REGISTRYINDEX);
if (lua_islightuserdata(L,-1))
ret=(swig_module_info*)lua_touserdata(L,-1);
lua_pop(L,1); // tidy
return ret;
}
SWIGRUNTIME void
SWIG_Lua_SetModule(lua_State* L, swig_module_info *module) {
// add this all into the Lua registry:
lua_pushstring(L,"swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME);
lua_pushlightuserdata(L,(void*)module);
lua_rawset(L,LUA_REGISTRYINDEX);
}
#ifdef __cplusplus
}
#endif
/*************************** end luarun.swg ******************************/

490
SWIG/Lib/lua/typemaps.i Normal file
View file

@ -0,0 +1,490 @@
/***********************************************************************
* typemaps.swg
*
* This file contains the main typemap code to support Lua modules
*
* Author : Mark Gossage (mark@gossage.cjb.net)
************************************************************************/
/* -----------------------------------------------------------------------------
* Basic inout typemaps
* ----------------------------------------------------------------------------- */
/*
These provide the basic ability for passing in & out of standard numeric data types
(int,long,float,double, etc)
The basic code looks like this:
%typemap(in,checkfn="lua_isnumber") int *INPUT(int temp), int &INPUT(int temp)
%{ temp = (int)lua_tonumber(L,$input);
$1 = &temp; %}
%typemap(in, numinputs=0) int *OUTPUT (int temp)
%{ $1 = &temp; %}
%typemap(argout) int *OUTPUT
%{ lua_pushnumber(L, (double) *$1); SWIG_arg++;%}
%typemap(in) int *INOUT = int *INPUT;
%typemap(argout) int *INOUT = int *OUTPUT;
However the code below is a mixture of #defines & such, so nowhere as easy to read
To make you code work correctly its not just a matter of %including this file
You also have to give SWIG the hints on which to use where
eg
extern int add_pointer(int* a1,int* a2); // a1 & a2 are pointer values to be added
extern void swap(int* s1, int* s2); // does the swap
You will need to either change the argument names
extern int add_pointer(int* INPUT,int* INPUT);
or provide a %apply statement
%apply int* INOUT{ int *s1, int *s2 };
// if SWIG sees int* s1, int* s2, assume they are inout params
*/
%define SWIG_NUMBER_TYPEMAP(TYPE)
%typemap(in,checkfn="lua_isnumber") TYPE *INPUT($*type temp), TYPE &INPUT($*type temp)
%{ temp = ($*type)lua_tonumber(L,$input);
$1 = &temp; %}
%typemap(in, numinputs=0) TYPE *OUTPUT ($*type temp)
%{ $1 = &temp; %}
%typemap(argout) TYPE *OUTPUT
%{ lua_pushnumber(L, (double) *$1); SWIG_arg++;%}
%typemap(in) TYPE *INOUT = TYPE *INPUT;
%typemap(argout) TYPE *INOUT = TYPE *OUTPUT;
// const version (the $*ltype is the basic number without ptr or const's)
%typemap(in,checkfn="lua_isnumber") const TYPE *INPUT($*ltype temp)
%{ temp = ($*ltype)lua_tonumber(L,$input);
$1 = &temp; %}
%enddef
// now the code
SWIG_NUMBER_TYPEMAP(int); SWIG_NUMBER_TYPEMAP(unsigned int);
SWIG_NUMBER_TYPEMAP(short); SWIG_NUMBER_TYPEMAP(unsigned short);
SWIG_NUMBER_TYPEMAP(long); SWIG_NUMBER_TYPEMAP(unsigned long);
SWIG_NUMBER_TYPEMAP(float);
SWIG_NUMBER_TYPEMAP(double);
SWIG_NUMBER_TYPEMAP(enum SWIGTYPE);
// note we dont do char, as a char* is probably a string not a ptr to a single char
/* -----------------------------------------------------------------------------
* Basic Array typemaps
* ----------------------------------------------------------------------------- */
/*
I have no idea why this kind of code does not exist in SWIG as standard,
but here is it.
This code will convert to/from 1D numeric arrays.
In order to reduce code bloat, there are a few macros
and quite a few functions defined
(unfortunately this makes it a lot less clear)
assuming we have functions
void process_array(int arr[3]); // nice fixed size array
void process_var_array(float arr[],int len); // variable sized array
void process_var_array_inout(double arr*,int len); // variable sized array
// data passed in & out
void process_enum_inout_array_var(enum Days *arrinout, int len); // using enums
void return_array_5(int arrout[5]); // out array only
in order to wrap them correctly requires a typemap
// inform SWIG of the correct typemap
// For fixed length, you must specify it as <type> INPUT[ANY]
%apply (int INPUT[ANY]) {(int arr[3])};
// variable length arrays are just the same
%apply (float INPUT[],int) {(float arr[],int len)};
// it is also ok, to map the TYPE* instead of a TYPE[]
%apply (double *INOUT,int) {(double arr*,int len)};
// for the enum's you must use enum SWIGTYPE
%apply (enum SWIGTYPE *INOUT,int) {(enum Days *arrinout, int len)};
// fixed length out if also fine
%apply (int OUTPUT[ANY]) {(int arrout[5])};
Generally, you could use %typemap(...)=...
but the %apply is neater & easier
a few things of note:
* all Lua tables are indexed from 1, all C/C++ arrays are indexed from 0
therefore t={6,5,3} -- t[1]==6, t[2]==5, t[3]==3
when passed to process_array(int arr[3]) becomes
arr[0]==6, arr[1]==5, arr[2]==3
* for OUTPUT arrays, no array need be passed in, the fn will return a Lua table
so for the above mentioned return_array_5() would look like
arr=return_array_5() -- no parameters passed in
* for INOUT arrays, a table must be passed in, and a new table will be returned
(this is consistant with the way that numbers are processed
if you want just use
arr={...}
arr=process_var_array_inout(arr) -- arr is replaced by the new version
The following are not yet supported:
* variable length output only array (inout's work ok)
* multidimentional arrays
* arrays of objects/structs
* arrays of pointers
*/
/*
The internals of the array managment stuff
helper fns/macros
SWIG_ALLOC_ARRAY(TYPE,LEN) // returns a typed array TYPE[LEN]
SWIG_FREE_ARRAY(PTR) // delete the ptr (if not zero)
// counts the specified table & gets the size
// integer version
int SWIG_itable_size(lua_State* L, int index);
// other version
int SWIG_table_size(lua_State* L, int index);
SWIG_DECLARE_TYPEMAP_ARR_FN(NAME,TYPE)
// this fn declares up 4 functions for helping to read/write tables
// these can then be called by the macros ...
// all assume the table is an integer indexes from 1
// but the C array is a indexed from 0
// created a fixed size array, reads the specified table
// and then fills the array with numbers
// returns ptr to the array if ok, or 0 for error
// (also pushes a error message to the stack)
TYPE* SWIG_get_NAME_num_array_fixed(lua_State* L, int index, int size);
// as per SWIG_get_NAME_num_array_fixed()
// but reads the entire table & creates an array of the correct size
// (if the table is empty, it returns an error rather than a zero length array)
TYPE* SWIG_get_NAME_num_array_var(lua_State* L, int index, int* size);
// writes a table to Lua with all the specified numbers
void SWIG_write_NAME_num_array(lua_State* L,TYPE *array,int size);
// read the specified table, and fills the array with numbers
// returns 1 of ok (only fails if it doesnt find numbers)
// helper fn (called by SWIG_get_NAME_num_array_*() fns)
int SWIG_read_NAME_num_array(lua_State* L,int index,TYPE *array,int size);
*/
%{
#ifdef __cplusplus /* generic alloc/dealloc fns*/
#define SWIG_ALLOC_ARRAY(TYPE,LEN) new (TYPE)[LEN]
#define SWIG_FREE_ARRAY(PTR) if(PTR){delete[] PTR;}
#else
#define SWIG_ALLOC_ARRAY(TYPE,LEN) (TYPE *)malloc(LEN*sizeof(TYPE))
#define SWIG_FREE_ARRAY(PTR) if(PTR){free(PTR);}
#endif
/* counting the size of arrays:*/
int SWIG_itable_size(lua_State* L, int index)
{
int n=0;
while(1){
lua_rawgeti(L,index,n+1);
if (lua_isnil(L,-1))break;
++n;
lua_pop(L,1);
}
lua_pop(L,1);
return n;
}
int SWIG_table_size(lua_State* L, int index)
{
int n=0;
lua_pushnil(L); /* first key*/
while (lua_next(L, index) != 0) {
++n;
lua_pop(L, 1); /* removes `value'; keeps `key' for next iteration*/
}
return n;
}
/* super macro to declare array typemap helper fns */
#define SWIG_DECLARE_TYPEMAP_ARR_FN(NAME,TYPE)\
int SWIG_read_##NAME##_num_array(lua_State* L,int index,TYPE *array,int size){\
int i;\
for (i = 0; i < size; i++) {\
lua_rawgeti(L,index,i+1);\
if (lua_isnumber(L,-1)){\
array[i] = (TYPE)lua_tonumber(L,-1);\
} else {\
lua_pop(L,1);\
return 0;\
}\
lua_pop(L,1);\
}\
return 1;\
}\
static TYPE* SWIG_get_##NAME##_num_array_fixed(lua_State* L, int index, int size){\
TYPE *array;\
if (!lua_istable(L,index) || SWIG_itable_size(L,index) != size) {\
lua_pushfstring(L,"expected a table of size %d",size);\
return 0;\
}\
array=SWIG_ALLOC_ARRAY(TYPE,size);\
if (!SWIG_read_##NAME##_num_array(L,index,array,size)){\
lua_pushstring(L,"table must contain numbers");\
SWIG_FREE_ARRAY(array);\
return 0;\
}\
return array;\
}\
static TYPE* SWIG_get_##NAME##_num_array_var(lua_State* L, int index, int* size)\
{\
TYPE *array;\
if (!lua_istable(L,index)) {\
lua_pushstring(L,"expected a table");\
return 0;\
}\
*size=SWIG_itable_size(L,index);\
if (*size<1){\
lua_pushstring(L,"table appears to be empty");\
return 0;\
}\
array=SWIG_ALLOC_ARRAY(TYPE,*size);\
if (!SWIG_read_##NAME##_num_array(L,index,array,*size)){\
lua_pushstring(L,"table must contain numbers");\
SWIG_FREE_ARRAY(array);\
return 0;\
}\
return array;\
}\
void SWIG_write_##NAME##_num_array(lua_State* L,TYPE *array,int size){\
int i;\
lua_newtable(L);\
for (i = 0; i < size; i++){\
lua_pushnumber(L,(double)array[i]);\
lua_rawseti(L,-2,i+1);/* -1 is the number, -2 is the table*/ \
}\
}
%}
/*
This is one giant macro to define the typemaps & the helpers
for array handling
*/
%define SWIG_TYPEMAP_NUM_ARR(NAME,TYPE)
%{SWIG_DECLARE_TYPEMAP_ARR_FN(NAME,TYPE);%}
// fixed size array's
%typemap(in) TYPE INPUT[ANY]
%{ $1 = SWIG_get_##NAME##_num_array_fixed(L,$input,$1_dim0);
if (!$1) SWIG_fail;%}
%typemap(freearg) TYPE INPUT[ANY]
%{ SWIG_FREE_ARRAY($1);%}
// variable size array's
%typemap(in) (TYPE *INPUT,int)
%{ $1 = SWIG_get_##NAME##_num_array_var(L,$input,&$2);
if (!$1) SWIG_fail;%}
%typemap(freearg) (TYPE *INPUT,int)
%{ SWIG_FREE_ARRAY($1);%}
// out fixed arrays
%typemap(in,numargs=0) TYPE OUTPUT[ANY]
%{ $1 = SWIG_ALLOC_ARRAY(TYPE,$1_dim0); %}
%typemap(argout) TYPE OUTPUT[ANY]
%{ SWIG_write_##NAME##_num_array(L,$1,$1_dim0); SWIG_arg++; %}
%typemap(freearg) TYPE OUTPUT[ANY]
%{ SWIG_FREE_ARRAY($1); %}
// inout fixed arrays
%typemap(in) TYPE INOUT[ANY]=TYPE INPUT[ANY];
%typemap(argout) TYPE INOUT[ANY]=TYPE OUTPUT[ANY];
%typemap(freearg) TYPE INOUT[ANY]=TYPE INPUT[ANY];
// inout variable arrays
%typemap(in) (TYPE *INOUT,int)=(TYPE *INPUT,int);
%typemap(argout) (TYPE *INOUT,int)
%{ SWIG_write_##NAME##_num_array(L,$1,$2); SWIG_arg++; %}
%typemap(freearg) (TYPE *INOUT,int)=(TYPE *INPUT,int);
// TODO out variable arrays (is there a standard form for such things?)
%enddef
// the following line of code
// declares the C helper fns for the array typemaps
// as well as defining typemaps for
// fixed len arrays in & out, & variable length arrays in
SWIG_TYPEMAP_NUM_ARR(int,int);
SWIG_TYPEMAP_NUM_ARR(uint,unsigned int);
SWIG_TYPEMAP_NUM_ARR(short,short);
SWIG_TYPEMAP_NUM_ARR(ushort,unsigned short);
SWIG_TYPEMAP_NUM_ARR(long,long);
SWIG_TYPEMAP_NUM_ARR(ulong,unsigned long);
SWIG_TYPEMAP_NUM_ARR(float,float);
SWIG_TYPEMAP_NUM_ARR(double,double);
// again enums are a problem so they need their own type
// we use the int conversion routine & recast it
%typemap(in) enum SWIGTYPE INPUT[ANY]
%{ $1 = ($ltype)SWIG_get_int_num_array_fixed(L,$input,$1_dim0);
if (!$1) SWIG_fail;%}
%typemap(freearg) enum SWIGTYPE INPUT[ANY]
%{ SWIG_FREE_ARRAY($1);%}
// variable size array's
%typemap(in) (enum SWIGTYPE *INPUT,int)
%{ $1 = ($ltype)SWIG_get_int_num_array_var(L,$input,&$2);
if (!$1) SWIG_fail;%}
%typemap(freearg) (enum SWIGTYPE *INPUT,int)
%{ SWIG_FREE_ARRAY($1);%}
// out fixed arrays
%typemap(in,numargs=0) enum SWIGTYPE OUTPUT[ANY]
%{ $1 = SWIG_ALLOC_ARRAY(enum SWIGTYPE,$1_dim0); %}
%typemap(argout) enum SWIGTYPE OUTPUT[ANY]
%{ SWIG_write_int_num_array(L,(int*)$1,$1_dim0); SWIG_arg++; %}
%typemap(freearg) enum SWIGTYPE OUTPUT[ANY]
%{ SWIG_FREE_ARRAY($1); %}
// inout fixed arrays
%typemap(in) enum SWIGTYPE INOUT[ANY]=enum SWIGTYPE INPUT[ANY];
%typemap(argout) enum SWIGTYPE INOUT[ANY]=enum SWIGTYPE OUTPUT[ANY];
%typemap(freearg) enum SWIGTYPE INOUT[ANY]=enum SWIGTYPE INPUT[ANY];
// inout variable arrays
%typemap(in) (enum SWIGTYPE *INOUT,int)=(enum SWIGTYPE *INPUT,int);
%typemap(argout) (enum SWIGTYPE *INOUT,int)
%{ SWIG_write_int_num_array(L,(int*)$1,$2); SWIG_arg++; %}
%typemap(freearg) (enum SWIGTYPE *INOUT,int)=(enum SWIGTYPE *INPUT,int);
/* Surprisingly pointer arrays are easier:
this is because all ptr arrays become void**
so only a few fns are needed & a few casts
The function defined are
// created a fixed size array, reads the specified table
// and then fills the array with pointers (checking the type)
// returns ptr to the array if ok, or 0 for error
// (also pushes a error message to the stack)
void** SWIG_get_ptr_array_fixed(lua_State* L, int index, int size,swig_type_info *type);
// as per SWIG_get_ptr_array_fixed()
// but reads the entire table & creates an array of the correct size
// (if the table is empty, it returns an error rather than a zero length array)
void** SWIG_get_ptr_array_var(lua_State* L, int index, int* size,swig_type_info *type);
// writes a table to Lua with all the specified pointers
// all pointers have the ownership value 'own' (normally 0)
void SWIG_write_ptr_array(lua_State* L,void **array,int size,int own);
// read the specified table, and fills the array with ptrs
// returns 1 of ok (only fails if it doesnt find correct type of ptrs)
// helper fn (called by SWIG_get_ptr_array_*() fns)
int SWIG_read_ptr_array(lua_State* L,int index,void **array,int size,swig_type_info *type);
The key thing to remember is that it is assumed that there is no
modification of pointers ownership in the arrays
eg A fn:
void pointers_in(TYPE* arr[],int len);
will make copies of the pointer into a temp array and then pass it into the fn
Lua does not remeber that this fn held the pointers, so it is not safe to keep
these pointers until later
eg A fn:
void pointers_out(TYPE* arr[3]);
will return a table containing three pointers
however these pointers are NOT owned by Lua, merely borrowed
so if the C/C++ frees then Lua is not aware
*/
%{
int SWIG_read_ptr_array(lua_State* L,int index,void **array,int size,swig_type_info *type){
int i;
for (i = 0; i < size; i++) {
lua_rawgeti(L,index,i+1);
if (!lua_isuserdata(L,-1) || SWIG_ConvertPtr(L,-1,&array[i],type,0)==-1){
lua_pop(L,1);
return 0;
}
lua_pop(L,1);
}
return 1;
}
static void** SWIG_get_ptr_array_fixed(lua_State* L, int index, int size,swig_type_info *type){
void **array;
if (!lua_istable(L,index) || SWIG_itable_size(L,index) != size) {
lua_pushfstring(L,"expected a table of size %d",size);
return 0;
}
array=SWIG_ALLOC_ARRAY(void*,size);
if (!SWIG_read_ptr_array(L,index,array,size,type)){
lua_pushfstring(L,"table must contain pointers of type %s",type->name);
SWIG_FREE_ARRAY(array);
return 0;
}
return array;
}
static void** SWIG_get_ptr_array_var(lua_State* L, int index, int* size,swig_type_info *type){
void **array;
if (!lua_istable(L,index)) {
lua_pushstring(L,"expected a table");
return 0;
}
*size=SWIG_itable_size(L,index);
if (*size<1){
lua_pushstring(L,"table appears to be empty");
return 0;
}
array=SWIG_ALLOC_ARRAY(void*,*size);
if (!SWIG_read_ptr_array(L,index,array,*size,type)){
lua_pushfstring(L,"table must contain pointers of type %s",type->name);
SWIG_FREE_ARRAY(array);
return 0;
}
return array;
}
void SWIG_write_ptr_array(lua_State* L,void **array,int size,swig_type_info *type,int own){
int i;
lua_newtable(L);
for (i = 0; i < size; i++){
SWIG_NewPointerObj(L,array[i],type,own);
lua_rawseti(L,-2,i+1);/* -1 is the number, -2 is the table*/
}
}
%}
// fixed size array's
%typemap(in) SWIGTYPE* INPUT[ANY]
%{ $1 = ($ltype)SWIG_get_ptr_array_fixed(L,$input,$1_dim0,$*1_descriptor);
if (!$1) SWIG_fail;%}
%typemap(freearg) SWIGTYPE* INPUT[ANY]
%{ SWIG_FREE_ARRAY($1);%}
// variable size array's
%typemap(in) (SWIGTYPE **INPUT,int)
%{ $1 = ($ltype)SWIG_get_ptr_array_var(L,$input,&$2,$*1_descriptor);
if (!$1) SWIG_fail;%}
%typemap(freearg) (SWIGTYPE **INPUT,int)
%{ SWIG_FREE_ARRAY($1);%}
// out fixed arrays
%typemap(in,numargs=0) SWIGTYPE* OUTPUT[ANY]
%{ $1 = SWIG_ALLOC_ARRAY($*1_type,$1_dim0); %}
%typemap(argout) SWIGTYPE* OUTPUT[ANY]
%{ SWIG_write_ptr_array(L,(void**)$1,$1_dim0,$*1_descriptor,0); SWIG_arg++; %}
%typemap(freearg) SWIGTYPE* OUTPUT[ANY]
%{ SWIG_FREE_ARRAY($1); %}
// inout fixed arrays
%typemap(in) SWIGTYPE* INOUT[ANY]=SWIGTYPE* INPUT[ANY];
%typemap(argout) SWIGTYPE* INOUT[ANY]=SWIGTYPE* OUTPUT[ANY];
%typemap(freearg) SWIGTYPE* INOUT[ANY]=SWIGTYPE* INPUT[ANY];
// inout variable arrays
%typemap(in) (SWIGTYPE** INOUT,int)=(SWIGTYPE** INPUT,int);
%typemap(argout) (SWIGTYPE** INOUT,int)
%{ SWIG_write_ptr_array(L,(void**)$1,$2,$*1_descriptor,0); SWIG_arg++; %}
%typemap(freearg) (SWIGTYPE**INOUT,int)=(SWIGTYPE**INPUT,int);