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

假设我从GameBoard类中注册了以下方法:
long int GameBoard::testFunct(long int);作为Lua下的“ 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);


(IDelegate和MethodDelegatePtr用于注册方法,函数和函子,因此我以后可以调用它们)

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

如果我注册并调用不带任何参数的方法,则该方法有效。
但是,如果有等待long int GameBoard::testFunct(long int);执行的任何参数,那么我将遇到以下错误...


  在静态成员函数中,静态Tr tUnpackLuaArgs :: unpack(IDelegate *,lua_State *,ArgsValue ...)[with C = GameBoard,Tr = int,Args = {long int},ArgsValue = {std :: basic_string} ,lua_State = lua_State]':
  
  从'静态Tr tUnpackLuaArgs :: unpack(IDelegate *,lua_State *,ArgsValue ...)实例化[使用C = GameBoard,Tr = int,Args = {long int},ArgsValue = {},unsigned int i = 1u,lua_State = lua_State]'
  
  从“静态int LuaCall :: LuaCallback(lua_State *)[实例化为C = GameBoard,Args = {long int},lua_State = lua_State]”
  
  错误:与“(MethodDelegatePtr)(std :: basic_string&)”的调用不匹配
  
  注意:参数1从'std :: basic_string'到'long int&'的转换未知
  
  
  
  在静态成员函数'static Tr tUnpackLuaArgs :: unpack(IDelegate *,lua_State *,ArgsValue ...)[with C = GameBoard,Tr = int,Args = {long int},ArgsValue = {bool},lua_State = lua_State]':
  
  从'静态Tr tUnpackLuaArgs :: unpack(IDelegate *,lua_State *,ArgsValue ...)实例化[使用C = GameBoard,Tr = int,Args = {long int},ArgsValue = {},unsigned int i = 1u,lua_State = lua_State]'
  
  从“静态int LuaCall :: LuaCallback(lua_State *)[实例化为C = GameBoard,Args = {long int},lua_State = lua_State]”
  
  错误:与“(MethodDelegatePtr)(bool&)”的调用不匹配
  
  注意:参数1从'bool'到'long int&'的转换未知


我找不到为什么当我注册等待std::basic_string<char>的方法时,ArgsValue尝试通过boollong int的方法。它应该通过long 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;
    }
};


确实,如果我从LUA_TSTRING函数中的if / else中删除了LUA_TBOOLEANunpack,它确实可以编译并且可以正常工作。

最佳答案

照原样,如果您的代码包含例如tUnpackLuaArgs<1>::unpack,然后unpack的主体将立即实例化所有可能性(因为它们都可以在运行时达到,具体取决于Lua堆栈上参数的类型)。

这包括tUnpackLuaArgs<0>::apply<C, Tr, Args..., std::string>,这意味着当Argslong int,因为std::string无法转换为long int const&operator()期望的IDelegate

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

关于c++ - 使用可变参数模板从Lua函数回调(C api)提取参数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/10084290/

10-12 00:07
查看更多