0

我正在尝试编写一个类来提取从 Lua 函数调用(调用已注册 C 函数的 Lua 脚本)传递的参数并将它们传递给已注册的方法(我的代码片段中的 IDelegate),以便我可以执行它并返回值.

假设我从 GameBoard 类中注册了以下方法 :在 Lua 下注册long int GameBoard::testFunct(long int);“GB:testFunction” ,代码如下:

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);

IDelegateMethodDelegatePtr用于注册方法、函数和仿函数,以便我稍后调用它们

然后当我在 Lua 脚本中写入时LuaCall<I32,GameBoard,I32>::LuaCallback将调用(以 Lua 堆栈作为参数)GB:testFunction(17);,然后将触发注册的方法并返回等待的值。

如果我注册并调用一个没有任何参数的方法,它就可以工作。但是如果有任何参数等待long int GameBoard::testFunct(long int);,那么我有以下错误......

在静态成员函数中 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]':

从 '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]'</p>

从 'static int LuaCall::LuaCallback(lua_State*) [with C = GameBoard, Args = {long int}, lua_State = lua_State]'实例化</p>

错误:不匹配调用 '(MethodDelegatePtr) (std::basic_string&)'</p>

注意:没有已知的参数 1 从 'std::basic_string' 到 'long int&' 的转换</p>


在静态成员函数 'static Tr tUnpackLuaArgs<0u>::unpack(IDelegate*, lua_State*, ArgsValue ...) [with C = GameBoard, Tr = int, Args = {long int}, ArgsValue = {bool} , lua_State = lua_State]':

从 '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]'</p>

从 'static int LuaCall::LuaCallback(lua_State*) [with C = GameBoard, Args = {long int}, lua_State = lua_State]'实例化</p>

错误:不匹配调用 '(MethodDelegatePtr) (bool&)'</p>

注意:没有已知的参数 1 从 'bool' 到 'long int&' 的转换</p>

当我注册一个等待 a 的方法时,我无法找到为什么 ArgsValue 尝试传递 astd::basic_string<char>或a ...它应该传递 a 。boollong intlong int

这是我编写的用于提取来自 Lua 脚本函数调用的参数的类。

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... );
    }
};

这是我使用它的方式:

// 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;
    }
};

事实上,如果我从 if/else in函数中删除LUA_TSTRINGand the ,它确实可以编译并且工作正常。LUA_TBOOLEANunpack

4

1 回答 1

1

实际上,如果您的代码包含 eg tUnpackLuaArgs<1>::unpack,那么 的主体unpack将急切地实例化所有可能性(因为它们都可能在运行时到达,具体取决于 Lua 堆栈上的参数类型)。

这包括 eg tUnpackLuaArgs<0>::apply<C, Tr, Args..., std::string>,这意味着您在Argsis eg时得到错误,long int因为std::string无法转换为long int const&the operator()ofIDelegate期望的。

您实际上并不需要所有这些可能性:您已经知道您的期望(就像long int您的情况一样)。std::string当你想要 a 时提取along int是没有用的。因此,您应该尝试从 Lua 堆栈中提取您期望的内容(如果转换不起作用,则可能会出错,直到运行时您才会知道)。

于 2012-04-10T08:21:23.157 回答