我一直在阅读有关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 ++类实例函数的直接方法。 需要非会员功能。表用于跟踪功能。
我的问题:
作为最终和可能的单一问题:
我可能只是回到第一步并尝试再次吸收这些信息。 我还是不想发帖子。如果我设置它,我会回复自己。
答案 0 :(得分:3)
有很多问题,但原则上,如果我理解正确,你想要bind your C++ classes to Lua,有一个shared object lifetime和自动垃圾收集,并且能够在创建的对象上调用Lua函数C ++方面。
使用低级粘合代码或专用绑定库(例如LuaBridge和LuaState)都可以实现这一切。为方便起见和快速原型设计,我在答案中使用了LuaState。
尚不清楚为什么你想在Lua中定义一个简单的函数,例如Object_OnLoad
从C ++调用它,它会调用你在一个对象中创建的对象的方法。 C ++方面的范围相同。我猜,你的代码中有一个更复杂的图片,所以这样的Lua使用模式是合理的。在这种情况下,一个接一个:
这是一个声明性绑定,在调用任何其他Lua函数之前可以调用一次
void luabridge_bind(lua_State *L) {
luabridge::getGlobalNamespace(L)
.beginClass<MyObject>("MyObject")
.addConstructor<void(*)(), RefCountedPtr<MyObject> /* creation policy */ >()
.addFunction("RegisterEvent", &MyObject::RegisterEvent)
.endClass()
;
}
执行绑定:
lua::State state;
luabridge_bind(state.getState());
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手册,以便更好地了解您手中的可能性。