我有一个c ++主机,我使用tolua ++将一些类暴露给Lua。其中一个类有一个应该从lua注册回调的函数。因此,当C ++代码需要调用Lua注册函数时,它可以。然而,该函数是表/类函数。之前我已经用字符串函数名称(不是lua“类”的一部分)成功完成了这个,但是我很好奇我是否能以某种方式存储Lua函数而不是函数名。
我定义了我的lua类,如:
MyClass = {}
function MyClass:Create()
local obj = {}
-- copy all functions from MyClass table to this local obj and return it
local k,v
for k,v in pairs(obj) do
obj[k] = v
end
return obj
end
function MyClass:Enter()
self.CPlusClass = CPlusClass:Create() -- this is the C++ class creation, I defined a static function Create()
self.CPlusClass:RegisterCallback(15, self.Callback) -- this is where I want to pass this instances function to be called back from the C++ class
end
function MyClass:Callback(reader)
-- I want to be able to use self here as well so it needs to be the same instance
end
在MyClass中:Enter()是我想要注册lua“class”函数MyClass :: Callback的地方,可以从C ++对象中调用它。我如何将其传递给C ++函数?类型是什么,它将调用MyClass:来自C ++的Callback()也传入“self”,这样它就是类的“实例”?
所以我知道'self'指的是我创建的实际变量,我假设它将在变量名称的全局表中,但是当你在lua“class”里面时,我怎么能告诉变量名'self '也指的是?如果我能得到它我可以将它传递给我的C ++函数并将其存储为字符串,以便我可以调用getglobal来获取该特定的表,然后我也可以将表函数名称作为字符串传递给C ++我可以得到它,并称之为。但问题是,如何将'self'转换为它指向的实际变量名称,以便我可以在C ++中调用getglobal来获取该表?
答案 0 :(得分:3)
您将CPlusClass“class”从C ++导出到Lua:当然这个C ++类有一个RegisterCallback,它接受一个指向函数的指针或一个使用虚方法调度到正确对象的YourCallbackClass实例。然后你需要的是将YourCallbackClass导出到Lua:在幕后,Lua版本将创建一个实例并将其提供给你的C ++ RegisterCallback。 例如:
class CPlusClass {
public:
RegisterCallback(int val, CPlusCallback* cb) { ... store cb for later... }
};
class SomeObj; // type of Objects that you want to call back into
class CPlusCallback {
public:
typedef void (SomeObj::*Method)();
CPlusCallback(SomeObj* obj, Method method) { callee=obj; method=method; }
call() { callee->*Method(); }
private:
SomeObj* callee;
Method method;
};
你的CPlusCallback可能不同,这只是一个例子。例如,如果您只想要函数而不是方法,那么您不需要存储被调用者。如果你想要两者,那么CPlusCallback必须是基类,call()是虚拟的,派生类适当地实现细节。适应您的情况。
然后将CPlusCallback和SomeObj导出到Lua,然后你可以在Lua中执行:
somObj = SomeObj:Create()
function MyClass:Enter()
-- creates Lua instance of CPlusClass, with a user data for the C++
-- counterpart as member
self.CPlusClass = CPlusClass:Create()
self.CPlusCallback = CPlusCallback:Create(someObj, someObj.method)
self.CPlusClass:RegisterCallback(15, self.CPlusCallback)
end
其中上面假设someObj.method是您从C ++类SomeObj导出的方法,具有正确的签名void(SomeObj :: * Method)()。
答案 1 :(得分:2)
如果你想保留RegisterCallback
签名和操作(而不是增强它以某种方式理解对象方法回调),那么你需要创建一个闭包并将其作为回调传递。像这样:
function create_closure(obj, fun)
return function(...)
return obj[fun](...)
end
end
和
function MyClass:Enter()
self.CPlusClass = CPlusClass:Create() -- this is the C++ class creation, I defined a static function Create()
self.CPlusClass:RegisterCallback(15, create_closure(self, "Callback"))
end