0

Lua 関数呼び出し (登録済みの C 関数を呼び出す Lua スクリプト) から渡されたパラメーターを抽出し、それらを登録済みのメソッド (コード スニペットの IDelegate) に渡すクラスを作成して、実行して値を返すことができるようにしようとしています。 .

GameBoard クラスから次のメソッドを登録する とします。次のコードを使用して、Lua で"GB:testFunction"long int GameBoard::testFunct(long int);として登録します。

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 スクリプトに書き込むときに(Lua スタックをパラメーターとして)LuaCall<I32,GameBoard,I32>::LuaCallbackが呼び出され、登録されたメソッドが起動され、待機中の値が返されます。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>

注: 'std::basic_string' から 'long int&' への引数 1 の既知の変換はありません</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>

注: 'bool' から 'long int&' への引数 1 の既知の変換はありません</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 からと を削除するLUA_TSTRINGと、コンパイルされて正常に動作します。LUA_TBOOLEANunpack

4

1 に答える 1

1

そのままで、コードに eg が含まれている場合tUnpackLuaArgs<1>::unpack、 の本体はすべての可能性unpackを熱心にインスタンス化します (Lua スタックの引数の型に応じて実行時に到達できる可能性があるため)。

これには eg が含まれます。これは、 egが期待するに変換できないため、egのtUnpackLuaArgs<0>::apply<C, Tr, Args..., std::string>ときにエラーが発生することを意味します。Argslong intstd::stringlong int const&operator()IDelegate

実際にはこれらすべての可能性が必要なわけではありません。期待していることはすでにわかっています(long intあなたの場合のように)。std::string必要なときに を抽出しても意味long intがありません。代わりに、Lua スタックから期待どおりのものを抽出するようにしてください (実行時までわからない変換が機能しない場合は、エラーが発生する可能性があります)。

于 2012-04-10T08:21:23.157 に答える