gpt4 book ai didi

c++ - 绑定(bind)C++函数和以类为参数调用Lua函数

转载 作者:行者123 更新时间:2023-11-30 02:44:07 25 4
gpt4 key购买 nike

我一直在阅读有关 Lua/C++ 的文章,我对设计有疑问,希望能得到一些帮助。

我想要的:

我希望我的 C++ 类(由 C++ 创建和销毁)能够调用一个使用自身作为参数的 Lua 函数。

例如。

object.h

class Object
{
public:
Object(const std::string & onLoad, const std::string & onEvent);
~Object();

void OnLoad();

void RegisterEvent(const std::string & eventID);
void OnEvent(const std::string & eventID);

void SetValue(int value);

private:
int m_value;
std::string m_onLoad;
std::string m_onEvent;
};

object.cpp

Object::Object(const std::string & onLoad, const std::string & onEvent)
: m_value(0)
, m_onLoad(onLoad)
, m_onEvent(onEvent)
{
}

Object::~Object()
{
GAME->GetEventManager()->UnregisterListener(this);
}

void Object::OnLoad()
{
//
// call lua function [name store in: m_onLoad]
// eg. m_onLoad = Object_OnLoad
// in lua ->
// function Object_OnLoad(object)
//
}

void Object::RegisterEvent(const std::string & eventID)
{
GAME->GetEventManager()->RegisterEvent(this, eventID);
}

void Object::OnEvent()
{
//
// call lua function [name store in: m_onEvent]
// eg. m_onEvent = Object_OnEvent
// in lua ->
// function Object_OnEvent(object, eventID)
//
}

void Object::SetValue(int value)
{
m_value = value;
}

script.lua

function Object_OnLoad(object)
object:RegisterEvent("EVENT_CURRENT_HEALTH_CHANGED")
end

function Object_OnEvent(object, eventID)
if (eventID == "EVENT_CURRENT_HEALTH_CHANGED")
object:SetValue(GetCurrentHealth());

end

test.cpp

Object *pTest = new Object("Object_OnLoad", "Object_OnEvent");

pTest->OnLoad();

GAME->GetEventManager()->TriggerEvent(CEvent("EVENT_CURRENT_HEALTH_CHANGED"));

delete pTest;

阅读后:

据我所知,这不是分配 C++ 类实例函数的直接方法。需要非成员函数。表格用于跟踪功能。

我的问题:

  • 在调用 Lua 函数(Object_OnEvent(object, eventID) 等...)时,我将什么作为参数推送?它是指向对象的指针吗
  • Lua是怎么知道对象设计的
  • 我是否需要为每个对象或实例创建一个表
  • 我是否需要再次复制我打算在 Lua 中使用的所有函数,作为普通函数获取 ptr 以从中调用它

作为最后一个可能的单一问题:

  • 有什么地方可以让我获得有关我正在努力实现的上述目标的更多信息。

我可能只是回到第一步并尝试再次吸收这些信息。我仍然不想发帖。如果我设置好了,我会自己回贴。

最佳答案

问题很多,但是原则上,如果我没理解错的话,你要bind your C++ classes to Lua , 有一个 shared object lifetime和自动垃圾收集,并能够在 C++ 端创建的对象上调用 Lua 函数。

这一切都可以通过低级胶水代码或专用绑定(bind)库实现,例如 LuaBridgeLuaState .为了方便和快速制作原型(prototype),我的答案中使用了 LuaState。

目前还不清楚的是为什么你想在 Lua 中定义一个简单的函数,比如 Object_OnLoad 来从 C++ 调用它,它会调用你在同一个文件中创建的对象的方法C++ 方面的作用域。我猜想,您的代码中有更复杂的图片,因此这种 Lua 使用模式是合理的。在那种情况下,一个接一个:

成分

绑定(bind)类到Lua

这是一个声明性绑定(bind),您可以在调用任何其他 Lua 函数之前调用一次

void luabridge_bind(lua_State *L) {
luabridge::getGlobalNamespace(L)
.beginClass<MyObject>("MyObject")
.addConstructor<void(*)(), RefCountedPtr<MyObject> /* creation policy */ >()
.addFunction("RegisterEvent", &MyObject::RegisterEvent)
.endClass()
;
}

执行绑定(bind):

 lua::State state;
luabridge_bind(state.getState());

在 C++ 端对象上调用 lua 函数

不幸的是,LuaState 目前不能在调用参数中使用对象,而原语可以工作,即来自自述文件:

state.doString("function add(x, y) return x + y end");
int result = state["add"](1,2);

但是我们可以做的是临时创建一个全局变量实例(注意名称冲突)并调用它的函数。

准备脚本:

static const char *script =
"function Object_OnLoad(object)\n"
" object:RegisterEvent('EVENT_CURRENT_HEALTH_CHANGED')\n"
"end"
;
state.doString(script);

创建一个自动生命周期管理的对象:

auto my_obj = RefCountedPtr<MyObject>(new MyObject);

在对象上调用lua函数:

SetGlobal(state.getState(), "my_obj", my_obj);
state.doString("Object_OnLoad(my_obj); my_obj = nil");

SetGlobal 看起来像这样:

template <typename T>
void SetGlobal(lua_State* L, const char *name, T value) {
luabridge::push(L, value);
lua_setglobal(L, name);
}

一个完整的例子和注释

您可以在 Github 上找到完整的示例代码:try_luabridge.cpp

已编译并运行于 Travis CI .

可能性是无限的。这取决于您如何构建代码,因此,自然地,此答案不会提供立即满足您需求的代码。但是,我鼓励您阅读 Programming in Lua ,以及 LuaBridge 和 LuaState 手册,以更好地了解您手头的可能性。

关于c++ - 绑定(bind)C++函数和以类为参数调用Lua函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25498277/

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