From db5bb83440438b56b3048b96be69e904ab85cd81 Mon Sep 17 00:00:00 2001 From: Mark Gossage Date: Mon, 11 Sep 2006 06:45:03 +0000 Subject: [PATCH] added support for passing function pointers as well as native lua object into wrappered function added example funcptr3 git-svn-id: https://swig.svn.sourceforge.net/svnroot/swig/trunk@9264 626c5289-ae23-0410-ae9c-e8d60b6d4f22 --- SWIG/Examples/lua/check.list | 1 + SWIG/Examples/lua/funcptr3/.cvsignore | 13 +++ SWIG/Examples/lua/funcptr3/Makefile | 19 ++++ SWIG/Examples/lua/funcptr3/example.c | 19 ++++ SWIG/Examples/lua/funcptr3/example.h | 9 ++ SWIG/Examples/lua/funcptr3/example.i | 69 ++++++++++++++ SWIG/Examples/lua/funcptr3/runme.lua | 54 +++++++++++ SWIG/Lib/lua/lua_fnptr.i | 128 ++++++++++++++++++++++++++ 8 files changed, 312 insertions(+) create mode 100644 SWIG/Examples/lua/funcptr3/.cvsignore create mode 100644 SWIG/Examples/lua/funcptr3/Makefile create mode 100644 SWIG/Examples/lua/funcptr3/example.c create mode 100644 SWIG/Examples/lua/funcptr3/example.h create mode 100644 SWIG/Examples/lua/funcptr3/example.i create mode 100644 SWIG/Examples/lua/funcptr3/runme.lua create mode 100644 SWIG/Lib/lua/lua_fnptr.i diff --git a/SWIG/Examples/lua/check.list b/SWIG/Examples/lua/check.list index b98b94d4d..2055af1b9 100644 --- a/SWIG/Examples/lua/check.list +++ b/SWIG/Examples/lua/check.list @@ -2,6 +2,7 @@ class constants functest +funcptr3 pointer simple variables diff --git a/SWIG/Examples/lua/funcptr3/.cvsignore b/SWIG/Examples/lua/funcptr3/.cvsignore new file mode 100644 index 000000000..d111f30e8 --- /dev/null +++ b/SWIG/Examples/lua/funcptr3/.cvsignore @@ -0,0 +1,13 @@ +example.py +example.pyc +*_wrap.c +*_wrap.cxx +*.dll +*.dsw +*.exp +*.lib +*.ncb +*.opt +*.plg +Release +Debug diff --git a/SWIG/Examples/lua/funcptr3/Makefile b/SWIG/Examples/lua/funcptr3/Makefile new file mode 100644 index 000000000..6417ce20e --- /dev/null +++ b/SWIG/Examples/lua/funcptr3/Makefile @@ -0,0 +1,19 @@ +TOP = ../.. +SWIG = $(TOP)/../preinst-swig +CXXSRCS = example.c +TARGET = example +INTERFACE = example.i +LIBS = + +all:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='$(TARGET)' INTERFACE='$(INTERFACE)' lua + +static:: + $(MAKE) -f $(TOP)/Makefile CXXSRCS='$(CXXSRCS)' SWIG='$(SWIG)' \ + TARGET='mylua' INTERFACE='$(INTERFACE)' lua_static + +clean:: + $(MAKE) -f $(TOP)/Makefile lua_clean + +check: all diff --git a/SWIG/Examples/lua/funcptr3/example.c b/SWIG/Examples/lua/funcptr3/example.c new file mode 100644 index 000000000..5c4a3dabf --- /dev/null +++ b/SWIG/Examples/lua/funcptr3/example.c @@ -0,0 +1,19 @@ +/* File : example.c */ + +int do_op(int a, int b, int (*op)(int,int)) { + return (*op)(a,b); +} + +int add(int a, int b) { + return a+b; +} + +int sub(int a, int b) { + return a-b; +} + +int mul(int a, int b) { + return a*b; +} + +int (*funcvar)(int,int) = add; diff --git a/SWIG/Examples/lua/funcptr3/example.h b/SWIG/Examples/lua/funcptr3/example.h new file mode 100644 index 000000000..9936e24fc --- /dev/null +++ b/SWIG/Examples/lua/funcptr3/example.h @@ -0,0 +1,9 @@ +/* file: example.h */ + +extern int do_op(int,int, int (*op)(int,int)); +extern int add(int,int); +extern int sub(int,int); +extern int mul(int,int); + +extern int (*funcvar)(int,int); + diff --git a/SWIG/Examples/lua/funcptr3/example.i b/SWIG/Examples/lua/funcptr3/example.i new file mode 100644 index 000000000..501af1d89 --- /dev/null +++ b/SWIG/Examples/lua/funcptr3/example.i @@ -0,0 +1,69 @@ +/* File : example.i */ +/* +This demonstrates how to pass a lua function, into some C code and then call it. + +There are two examples, the first is as a parameter, the second as a global variable. + +*/ +%module example +%{ +#include "example.h" +%} +/* the extra wrappers for lua functions, see SWIG/Lib/lua/lua_fnptr.i for more details */ +%include "lua_fnptr.i" + +/* these are a bunch of C functions which we want to be able to call from lua */ +extern int add(int,int); +extern int sub(int,int); +extern int mul(int,int); + +/* this function takes a lua function as a parameter and calls it. +As this is takes a lua fn it needs lua code +*/ +%inline %{ + +int callback(int a, int b, SWIGLUA_FN fn) +{ + SWIGLUA_FN_GET(fn); + lua_pushnumber(fn.L,a); + lua_pushnumber(fn.L,b); + lua_call(fn.L,2,1); /* 2 in, 1 out */ + return luaL_checknumber(fn.L,-1); +} +%} + +/****************** +Second code uses a stored reference. +*******************/ + +%inline %{ +/* note: this is not so good to just have it as a raw ref + people could set anything to this + a better solution would to be to have a fn which wants a SWIGLUA_FN, then + checks the type & converts to a SWIGLUA_REF. +*/ +SWIGLUA_REF the_func={0,0}; + +void call_the_func(int a) +{ + int i; + if (the_func.L==0){ + printf("the_func is zero\n"); + return; + } + swiglua_ref_get(&the_func); + if (!lua_isfunction(the_func.L,-1)) + { + printf("the_func is not a function\n"); + return; + } + lua_pop(the_func.L,1); /* tidy stack */ + for(i=0;iL!=0 && pref->ref!=LUA_NOREF && pref->ref!=LUA_REFNIL){ + luaL_unref(pref->L,LUA_REGISTRYINDEX,pref->ref); + } + pref->L=0; pref->ref=0; +} + +void swiglua_ref_set(SWIGLUA_REF* pref,lua_State* L,int idx){ +// swiglua_ref_clear(pref); /* just in case */ + pref->L=L; + lua_pushvalue(L,idx); /* copy obj to top */ + pref->ref=luaL_ref(L,LUA_REGISTRYINDEX); /* remove obj from top & put into registry */ +} + +void swiglua_ref_get(SWIGLUA_REF* pref){ + if (pref->L!=0) + lua_rawgeti(pref->L,LUA_REGISTRYINDEX,pref->ref); +} + +%} + +%typemap(in) SWIGLUA_REF +%{ swiglua_ref_set(&$1,L,$input); %} + +%typemap(out) SWIGLUA_REF +%{ if ($1.L!=0) {swiglua_ref_get(&$1);} else {lua_pushnil(L);} + SWIG_arg++; %} +