[英]Binding C++ functions & calling Lua functions with class as parameter
我一直在閱讀有關 Lua/C++ 的文章,我有一個關於設計的問題,希望能得到一些幫助。
我想要的是:
我希望我的 C++ 類(由 C++ 創建和銷毀)能夠使用自身作為參數調用 Lua 函數。
例如。
對象.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;
};
對象.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;
}
腳本文件
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
測試.cpp
Object *pTest = new Object("Object_OnLoad", "Object_OnEvent");
pTest->OnLoad();
GAME->GetEventManager()->TriggerEvent(CEvent("EVENT_CURRENT_HEALTH_CHANGED"));
delete pTest;
經過一些閱讀:
從我讀過的內容來看,這不是分配 C++ 類實例函數的直接方法。 需要非成員函數。 表格用於跟蹤功能。
我的問題:
作為最后一個可能的單一問題:
我可能會回到第一步,再次嘗試吸收這些信息。 我仍然不想發表我的帖子。 如果我設置了它,我會自己發帖。
有很多問題,但原則上,如果我理解正確,您希望將 C++ 類綁定到 Lua ,具有共享對象生存期和自動垃圾收集,並且能夠在 C++ 端創建的對象上調用 Lua 函數。
這一切都可以通過低級膠水代碼或專用綁定庫(例如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());
不幸的是,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 手冊,以便更好地了解您手頭的可能性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.