I'm trying to write a class that extract the parameters passed from a Lua function call (Lua script calling a registered C function) and pass them to the registered method (IDelegate in my code snippets) so I can execute it and returns the value.
Suppose I register the following method from the GameBoard class:
long int GameBoard::testFunct(long int);
as "GB:testFunction" under Lua with the following code:
luaL_newmetatable(mState, "GameBoard");
lua_pushstring(mState, "__index");
lua_pushvalue(mState, -2);
lua_settable(mState, -3);
lua_pushstring(mState,"testFunction");
hbt::IDelegate<I32,I32>* ideleg = new MethodDelegatePtr<GameBoard,I32,I32>( NULL, &GameBoard::testFunct); // will be deleted later
lua_pushlightuserdata (mState, (IDelegate<I32,I32>*)ideleg);
lua_pushcclosure(mState, LuaCall<I32,GameBoard,I32>::LuaCallback,1);
lua_settable(mState,-3);
(IDelegate & MethodDelegatePtr are used to register methods, functions and functors so I can call them later)
then the LuaCall<I32,GameBoard,I32>::LuaCallback
will be called (with the Lua stack as parameter) when I will write GB:testFunction(17);
in the Lua-script, and then the registered method will be fired and the awaited value returned.
And it works If I register and call a method without any argument.
But if there is any parameter awaited as long int GameBoard::testFunct(long int);
do, then I have got the following errors...
In static member function static Tr tUnpackLuaArgs<0u>::unpack(IDelegate*, lua_State*, ArgsValue ...) [with C = GameBoard, Tr = int, Args = {long int}, ArgsValue = {std::basic_string}, lua_State = lua_State]’:
instantiated from ‘static Tr tUnpackLuaArgs::unpack(IDelegate*, lua_State*, ArgsValue ...) [with C = GameBoard, Tr = int, Args = {long int}, ArgsValue = {}, unsigned int i = 1u, lua_State = lua_State]’
instantiated from ‘static int LuaCall::LuaCallback(lua_State*) [with C = GameBoard, Args = {long int}, lua_State = lua_State]’
error: no match for call to ‘(MethodDelegatePtr) (std::basic_string&)’
note: no known conversion for argument 1 from ‘std::basic_string’ to ‘long int&’
In static member function ‘static Tr tUnpackLuaArgs<0u>::unpack(IDelegate*, lua_State*, ArgsValue ...) [with C = GameBoard, Tr = int, Args = {long int}, ArgsValue = {bool}, lua_State = lua_State]’:
instantiated from ‘static Tr tUnpackLuaArgs::unpack(IDelegate*, lua_State*, ArgsValue ...) [with C = GameBoard, Tr = int, Args = {long int}, ArgsValue = {}, unsigned int i = 1u, lua_State = lua_State]’
instantiated from ‘static int LuaCall::LuaCallback(lua_State*) [with C = GameBoard, Args = {long int}, lua_State = lua_State]’
error: no match for call to ‘(MethodDelegatePtr) (bool&)’
note: no known conversion for argument 1 from ‘bool’ to ‘long int&’
I'm unable to find why ArgsValue try to pass a std::basic_string<char>
or a bool
when I register a method awaiting for a long int
... It should pass a long int
.
And here is the class I wrote to extract the parameters coming from the Lua script function call.
template< unsigned int i >
class tUnpackLuaArgs
{
public:
template< class C, class Tr, class... Args, class... ArgsValue >
static Tr unpack( IDelegate<C,Tr,Args...>* ideleg, lua_State *L, ArgsValue... argsVal)
{
int t = lua_type(L, i+1);
if( t == LUA_TNUMBER)
{
I32 tmpUint = lua_tonumber(L, i+1);
return tUnpackLuaArgs< i-1 >::unpack( ideleg, L, argsVal..., tmpUint);
}
else if( t == LUA_TSTRING)
{
std::string tmpStr = lua_tostring(L, i+1);
return tUnpackLuaArgs< i-1 >::unpack( ideleg, L, argsVal..., tmpStr);
}
else if( t == LUA_TBOOLEAN)
{
bool tmpBool = lua_toboolean(L, i+1);
return tUnpackLuaArgs< i-1 >::unpack( ideleg, L, argsVal..., tmpBool);
}
//etc.
}
};
template<>
class tUnpackLuaArgs<0>
{
public:
template< class C, class Tr, class... Args, class... ArgsValue >
static Tr unpack( IDelegate<C,Tr,Args...>* ideleg, lua_State *L, ArgsValue... argsVal)
{
//-- Execute the registered method using the LUA arguments
//-- and returns the returned value
return (*ideleg)( argsVal... );
}
};
And here is how I use it:
// Specialized template returning an integer
template <class C, class... Args>
struct LuaCall<int, C, Args...>
{
static int LuaCallback(lua_State *L)
{
//-- retrieve method "IDelegate" from Lua stack etc.
//-- then call tUnpackLuaArgs with the arguments to push the returned value onto the lua stack
lua_pushnumber(L, tUnpackLuaArgs< sizeof...(Args) >::unpack(funcPtr,L));
return 1;
}
};
Indeed if I remove the LUA_TSTRING
and the LUA_TBOOLEAN
from the if/else in unpack
function, it does compile and works fine.