Lua callback from C++



我有一个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++函数中?该类型是什么样的,它将从C++调用MyClass:Callback(),同时传入"self",使其成为类的同一"实例"?

所以我知道"self"指的是我创建的一个实际变量,我假设它将按变量名在全局表中,但当你在lua"class"中时,我怎么能知道"self-"也指的是什么变量名?如果我能得到,我可以把它传递给我的C++函数,并将其存储为字符串,这样我就可以在它上调用getglobal来获得特定的表,然后我也可以把表函数名传递为字符串,在C++中我也可以得到它,并调用它。但问题是,如何将"self"转换为它所指向的实际变量名,以便在C++中调用getglobal来获取该表?

您将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)()。

如果您想保留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

最新更新