lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


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