gpt4 book ai didi

c++ - 在 C/C++ 中实现 __index 元函数

转载 作者:搜寻专家 更新时间:2023-10-31 02:06:04 24 4
gpt4 key购买 nike

我有一个 C++ 回调/仿函数系统的脚本,它可以使用字符串和/或变体调用任何“已注册”的 C++ 函数。

//REMOVED ERROR CHECKS AND ERRONEOUS STUFF FOR THIS POST
int LuaGameObject::LuaCallFunction( lua_State *luaState )
{
if ( lua_isuserdata( luaState, 1 ) == 1 )
{
int nArgs = lua_gettop( luaState );

//Get GameObject
OGameObject* pGameObject = static_cast<OGameObject*>(lua_touserdata( luaState, 1 ));
if ( pGameObject )
{
//Get FunctionName
const char* functionNameString = lua_tostring( luaState, 2 );

//Get Args
std::vector<OVariant> args;
for ( int i = 3; i <= nArgs; ++i )
{
OVariant variant;
variant.SetFromLua( luaState, i );
args.push_back( variant );
}

//Call it!
CallGameObjectFunction( luaState, pGameObject, functionNameString, args );

return 1;
}
}

return 0;
}

OVariant LuaGameObject::ExecuteLua()
{
lua_State *lState = luaL_newstate();

luaL_openlibs( lState );
lua_register( lState, "Call", LuaCallFunction );

luaL_loadstring( lState, m_pScript );

//now run it
lua_pcall( lState, 0, 1, 0 );

//process return values
OVariant result;
result.SetFromLua( lState, -1 );

lua_close( lState );

return result;
}

在 lua 中我可以做这样的事情......

local king = Call("EmpireManager","GetKing")
Call("MapCamera","ZoomToActor",king)

但是,我觉得我可以使用__index 元方法来简化lua...

local king = EmpireManager:GetKing()
MapCamera:ZoomToActor(king)

我希望通过使用以下 __index 元方法的实现来实现简化的 lua

下面是我如何注册 __index 元函数...(主要是从在线示例中复制的)

void LuaGameObject::Register( lua_State * l )
{
luaL_Reg sRegs[] =
{
{ "__index", &LuaGameObject::LuaCallFunction },
{ NULL, NULL }
};

luaL_newmetatable( l, "luaL_EmpireManager" );

// Register the C functions into the metatable we just created.
luaL_setfuncs( l, sRegs, 0 );
lua_pushvalue( l, -1 );

// Set the "__index" field of the metatable to point to itself
// This pops the stack
lua_setfield( l, -1, "__index" );

// Now we use setglobal to officially expose the luaL_EmpireManager metatable
// to Lua. And we use the name "EmpireManager".
lua_setglobal( l, "EmpireManager" );
}

不幸的是,我似乎无法正确设置回调。 Lua 正确调用了我的 LuaGameObject::LuaCallFunction,但堆栈不包含我想要的内容。在 LuaGameObject::LuaCallFunction 中,我可以在堆栈上找到函数名称和 EmpireManager 对象。但是,我无法在堆栈中找到 args。设置它的正确方法是什么?还是不可能?

最佳答案

在 Lua 中向 userdata 类型添加方法绝对是可能的,如 Programming in Lua 中所述。官网指南。

当您键入以下 Lua 代码时:

myUserdata:someMethod(arg1,arg2,arg3)

假设 myUserdata 是一个“userdata”对象,解释器将执行以下操作。

  1. 调用getmetatable(myUserdata).__index(myUserdata,"someMethod")获取someMethod的值。
  2. 调用 someMethod(myUserdata,arg1,arg2,arg3)someMethod 可以是任何可从 Lua 调用的方法。示例:Lua 或 C 函数,或带有 __call 元方法的表/用户数据。

你的 __index 元方法应该只返回一个实现该方法的函数(或另一个可从 Lua 调用的对象)。像这样:

// IMO, quite a misleading name for the __index metamethod (there is a __call metamethod)
int LuaGameObject::LuaCallFunction( lua_State *l)
{
// todo: error checking
OGameObject* pGameObject = static_cast<OGameObject*>(lua_touserdata( luaState, 1 ));
std::string memberName = lua_tostring( luaState, 2 );

int result = 1;
if (memberName == "method1") {
lua_pushcfunction(l,LuaGameObject::luaMethod1);
} else if (memberName == "method2") {
lua_pushcfunction(l,LuaGameObject::luaMethod2);
} else {
result = 0;
}

return result;
}

__index 元方法返回的函数的基本框架:

int LuaGameObject::luaMethod1(lua_State* l) {
// todo: error checking.
OGameObject* pGameObject = static_cast<OGameObject*>(lua_touserdata(l, 1));
float arg1 = lua_tonumber(l, 2);
// get other args
pGameObject->method1(arg1 /*, more args if any.*/);
// optionally push return values on the stack.
return 0; // <-- number of return values.
}

关于c++ - 在 C/C++ 中实现 __index 元函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50880830/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com