Reputation: 1693
I'm still very new to Lua and I have a hard time trying to figure out the best approach when registering C functions in Lua, but from a C++ class, when it comes to retrieving the self pointer from an object that was not created from Lua.
Consider the following code:
class Foo
{
public:
static int lua_DoSomething(lua_State* pState);
void DoSomething();
};
static const luaL_Reg methods[] =
{
{"DoSomething", Foo::lua_DoSomething},
{nullptr, nullptr}
};
extern "C"
{
int luaopen_Foo(lua_State* pState)
{
luaL_register(pState, "Foo", methods);
return 1;
}
}
int Foo::lua_DoSomething(lua_State* pState)
{
Foo* self = ???; //<-- how to get self pointer here?
self->DoSomething();
return 0;
}
void Foo::DoSomething()
{
//...
}
Foo.DoSomething();
So I got the function registered just fine and Foo::lua_DoSomething
gets called (yay!).
However, since the Foo
object is not created from Lua, how would I go to get the self pointer in function Foo::lua_DoSomething
?
Do I have to register some kind of Foo::GetInstance
function to Lua, to get the Foo
pointer, and then use it in the Lua script somehow?
And what if there's multiple instance of Foo
?
What's the cleanest general approach for objects not created from Lua?
Thanks!
Upvotes: 0
Views: 1208
Reputation: 141
You need to pass some information in the lua state, which will help you identify the "self". For example you can store all created instances of the Foo class in map, associate an instance with some identifier (int id), or just pass the pointer of the instance cast to size_t. Then in the lua_DoSomething method, get that information from the lua state, cast it to the Foo instance and you have the "self".
post edit:
I am not very familiar with lua from this side (I have done some scripting in lua). But...
In lua you can store data and you can exchange this data between lua and C++.
I guess you have counter part of C++ Foo in lua, lets name it LFoo.
Foo in C++ has the method DoSomething and I guess you want to do same in lua (I know you can't have classes in lua but there are ways to mimic it with tables). Foo instance has it's address (this). Pass this address to lua and store the value in table of LFoo. When you call the DoSomething function in lua, this function will call static method lua_DoSomething, pass the value from LFoo table through lua_state back to that method. Use it to get "this".
Try to use something like this:
void RegisterFoo(lua_state* pState, Foo* foo)
{
Foo** p = (Foo**)lua_newuserdata(pState,sizeof(foo));
*p = foo;
...
}
int Foo::lua_DoSomething(lua_State* pState)
{
// pass the pointer at first index for example
Foo* self = (Foo*)lua_topointer(pState,0);
self->DoSomething();
return 0;
}
I have found this explanation of these functions:
http://pgl.yoyo.org/luai/i/lua_newuserdata
http://pgl.yoyo.org/luai/i/lua_topointer
Upvotes: 0
Reputation: 283
In member functions of type Foo, the 'this' pointer is provided for you automatically. Its type is of const Foo*. It is not normally necessary, because in most cases you can just use the member directly. Eg: you can replace:
int Foo::lua_DoSomething(lua_State* pState)
{
this->DoSomething();
return 0;
}
with
int Foo::lua_DoSomething(lua_State* pState)
{
DoSomething();
return 0;
}
Upvotes: -2