[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Conversion Lua function to C function
- From: Duncan Cross <duncan.cross@...>
- Date: Sat, 17 Oct 2009 17:47:14 +0100
2009/10/17 Jiří Prymus <jiri.prymus@gmail.com>:
> Thanks for answers.
>
> I'm little confused from yours replies but I try to explain my problem clearly.
> I need to pass lua function to C++ wrapper function where it will be
> used as "update event" of GtkTrackBar widget.
> My wrapper is compiled as shared library for lua.
>
> Maybe that sample code make this problem clear.
>
> C++ wrapper function -----------------
>
> static int luacv_cvCreateTrackbar(lua_State *L)
> {
> const char *trackbar_name=luaL_checkstring(L,1);
> const char *window_name=luaL_checkstring(L,2);
> int value=luaL_checkint(L,3);
> int count=luaL_checkint(L,4);
> CvTrackbarCallback on_change=NULL;
>
> if (lua_isfunction(L,5))
> on_change=(CvTrackbarCallback)lua_tocfunction(L,5);
> else
> luaL_error(L,"luacv.cvCreateTrackbar(string trackbar_name,string
> window_name,int value,int count, void func(int pos))");
>
> cvCreateTrackbar(trackbar_name,window_name,&value,count,on_change);
>
> return 0;
> }
>
> Type CvTrackbarCallback is defined like
> typedef void (CV_CDECL *CvTrackbarCallback)(int pos);
>
> As you can see , the "on_change" variable is pointer to c function
> with int as argument.
>
> Lua script may be look like this
>
> cv=require('luacv')
>
> function on_trackbar(pos)
> ...do some stuff here..
> end
>
> cv.cvCreateTrackbar(tbarname,wndname,edge_thresh,100,on_trackbar)
>
>
> So I can get pointer of lua function "on_trackbar" via stack in
> wrapper , but when I want to convert it to c function, it doesn't
> work.
You cannot get a pointer to a Lua function from C and call it directly
as if it were a C function. There is no way to convert it. Instead,
you must always get the Lua function onto the stack (from somewhere
already inside the Lua "universe"), and call it using
lua_call()/lua_pcall().
The trick is finding the right place to store it. Ideally you don't
want to be doing any more than a single table lookup to get your
function.
For example, you could decide that the place to look for your function
is a global variable with a specific name:
lua_getglobal(L, "on_trackbar");
if (lua_isfunction(L,-1)) {
lua_call(L,0,0);
}
Or, you could use the luaL_ref()/luaL_unref() system (look them up in
the Reference Manual if you have not used them before) to get an
integer reference to your function:
// Lua function on_trackbar() is on top of the stack
int on_trackbar_id = luaL_ref(L, LUA_REGISTRYINDEX);
// on_trackbar() has been removed from the stack,
// and stored in the registry table. on_trackbar_id now stores
// a unique identifier for it.
// ... later on, when we want to call on_trackbar():
luaL_unref(L, LUA_REGISTRYINDEX, on_trackbar_id);
// on_trackbar() is back on top of the stack again, so we can call it:
lua_call(L,0,0);
There are other options as well, but it's all basically variations on
the same thing.
-Duncan