我正在嘗試編寫一個類,該類提取從Lua函數調用(Lua腳本調用已註冊的C函數)傳遞的參數,並將它們傳遞給已註冊方法(IDelegate在我的代碼片段),所以我可以執行它並返回值。使用可變參數模板從Lua函數回調(C api)提取參數
假設我寄存器從遊戲鍵盤類下面的方法: long int GameBoard::testFunct(long int);
如「GB:testFunction」的Lua下用下面的代碼:
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用於註冊方法,函數和函數,所以我可以稍後給他們打電話)
然後LuaCall<I32,GameBoard,I32>::LuaCallback
將被稱爲(以Lua堆棧爲參數)當我將在Lua腳本中寫入GB:testFunction(17);
,然後註冊的方法將被觸發並返回等待的值。
它的工作原理如果我註冊並調用一個沒有任何參數的方法。 但如果等待爲long int GameBoard::testFunct(long int);
任何參數做的話,我已經得到了以下錯誤......
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&’
我找不到爲什麼ArgsValue試圖通過一個std::basic_string<char>
或當我註冊的方法bool
等待long 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
和LUA_TBOOLEAN
從的if/else在unpack
功能,它編譯和工作正常。
需要注意的是,'tUnpackLuaArgs :: unpack'實例化後的實例化數量是N^d的數量級,其中根據您的代碼,d似乎至少爲3。爲了避免這種情況,你會在編譯時做得很好。 –
2012-04-10 08:29:56
我仍然不知道如何提取這些參數,但是您的解釋很明確,並確認了我被懷疑出現此問題的原因。謝謝。 – Valkea 2012-04-10 17:28:46
@Valkea你可能會感興趣的[一個解決方案](http://stackoverflow.com/questions/10014713/build-tuple-using-variadic-templates#comment12805453_10014713)使用元組沒有遞歸(它也有用時,當沒有元組參與)。請注意,這裏不可能使用遞歸。 – 2012-04-10 17:53:02