[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: passing pointers using LuaBridge
- From: Moose <moose@...>
- Date: Mon, 07 Apr 2014 15:36:19 +0200
All right. At last....
if anybody cares for an answer.... After so many tries I have ditched
all efforts to get a C++ bridge to work. Instead I focused on the C API
and managed to pass pointers in using a modified version of my init. So,
to answer it, please let me write what I would have loved to read when
starting those efforts.
/* NOT part of C API */
void inject_myclass(lua_State *L, MyClass *n_my_class) {
/* store the pointer to MyClass in global registry */
lua_pushlightuserdata(L, (void *)&KeyMyClass ); /* push address is
some static data. Could be anything */
lua_pushlightuserdata(L, n_my_class); /* push value
*/
/* registry[&KeyMyClass] = ret */
lua_settable(L, LUA_REGISTRYINDEX);
}
/* part of C API */
int myclass_foo() {
/* retrieve the pointer to MyClass from registry */
lua_pushlightuserdata(L, (void *)&KeyMyClass ); /* push address */
lua_gettable(L, LUA_REGISTRYINDEX); /* retrieve value */
MyClass * mc = (MyClass *)lua_topointer(L, -1); /* convert to pointer
*/
mc->foo();
return 0;
}
... wrap it all up in a C exposed API ...
And then, when using it:
lua_State *L = luaL_newstate();
luaL_openlibs(L);
// call the module open function manually that would have been called
by require()
// With doing so, you don't have to require() your module within your
script
// and still use all your C API
// So your DLL only is loaded once and no overhead.
luaopen_my_module(L);
// just as an example, create your object
MyClass *mc = new MyClass()
// inject into your running context.
// With doing so, you replace the need to create your object
// inside the context but re-use it.
inject_myclass(L, mc);
if (luaL_dofile(L, "luatest_reuse.lua")) {
std::cerr << "Lua program returned an error: \n";
std::cerr << lua_tostring(L, -1);
std::cerr << std::endl;
lua_close(L);
}
// Your object is alive and well after that
delete mc;
So your script can be as simple as that...
[[
mymodule.foo()
]]
...and will call foo() on your object, leaving it alive.
Concluding I would like to add that while this serves the purpose that
I originally started with, it is hard for me to understand the hassle
that comes with it. The use cases strikes me as one of the simplest
things that I could do with an embedded language and I cannot believe
how complicated it was and how much time it cost me to make this happen.
And how much of a hack this seems to me. It just screams non-canonical.
All this messing around with lightuserdata. The name itself... I don't
know. Isn't that a standard use case for an embedded language to use
things outside? Wouldn't it be better to offer one function that exposes
the pointer inside the script and call it push_pointer() or some such
understandable way? The three lines that do the trick in my example
above say to me "I'm using that mechanism called lightuserdata although
this is meant for something else."
Also, please let me add a tad criticism. When I look at the wiki page
for language bindings ( http://lua-users.org/wiki/BindingCodeToLua ) I
see no less than 22 projects and mechanisms that bind C++ for use inside
Lua. After filtering out the projects that are dead, unmaintained or
require an own library and therefore link dependency I ended up with a
handful of candidates, three of which I pursued to a working
implementation (including LuaJit ffi). And none worked with objects
being passed into. Out of 22. Seriously? Sorry for sounding harsh but it
seems preferable to me to have one working solution instead of 22. It
may be because of MSVC90 here but it's not like that's a niche compiler
that nobody really uses.
Does the Lua community pursue any efforts in centralizing those
projects and perhaps boil them down for direct inclusion into the
distribution? Or maybe recommend one?
</rant>
Sorry for this, but sometimes it can be helpful to know how outsiders
see a system.
In any case, thank you so much for your help. It was very interesting
to get to know Lua. I'm gonna do some trials now and see how it performs
and compares to other candidates.
Cheers,
Stephan