Lua回调函数从C++中
我有一个 C++ 宿主程序,使用 tolua++ 将一些类暴露给 Lua 使用。其中一个类有一个函数应该从 Lua 中注册回调。这样当 C++ 代码需要调用一个已注册的 Lua 函数时,就可以通过这个回调函数实现。但是该函数是一个表/类函数。我以前使用字符串函数名(不是 Lua “类”的一部分)成功的注册过,但我想知道是否能以某种方式存储 Lua 函数,而不是函数名。
我定义我的 Lua 类如下:
MyClass = {}
function MyClass:Create()
local obj = {}
-- 复制 MyClass 表中的所有函数到此本地 obj 并返回它们
local k, v
for k, v in pairs(obj) do
obj[k] = v
end
return obj
end
function MyClass:Enter()
self.CPlusClass = CPlusClass:Create() -- 这是 C++ 类创建,我定义了一个静态函数 Create()
self.CPlusClass:RegisterCallback(15, self.Callback) -- 这是我想要传递这个实例函数,以便从 C++ 类回调时调用
end
function MyClass:Callback(reader)
-- 我想要能够在这里使用 self,因此需要是同一个实例
end
我想在 MyClass:Enter() 内注册 Lua“类”函数 MyClass::Callback,以便能够从 C++ 对象调用它。我该如何将此传递给 C++ 函数?类型将是什么,以便从 C++ 中调用 MyClass:Callback(),同时将“self”传递,以便它是同一个类的“实例”?
我知道“self”是指我创建的实际变量,我假设它会通过变量名在全局表中,但当你在 Lua “类”内部时,我该如何确定“self”指向的变量名是什么?如果我能够得到它,我就可以将其作为字符串传递给我的 C++ 函数,并将其存储为字符串,以便我可以调用它来获取该特定表。然后我也可以将表函数名作为字符串传递,并在 C++ 中获取它并调用它。但问题是如何将“self”转换为它指向的实际变量名,以便我可以在 C++ 中调用 getglobal 来获取该表?
你将 C++ 的 CPlusClass "class" 导出到了 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()
-- 在创建 Lua 的 CPlusClass 实例时,使用一个 C++ 的用户数据作为成员
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)()。
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
如果您想保留
RegisterCallback的签名和操作(而不是以某种方式增强其理解对象方法回调),则需要创建一个闭包并将其作为回调传递。像这样:function create_closure(obj, fun) return function(...) return obj[fun](...) end end和
function MyClass:Enter() self.CPlusClass = CPlusClass:Create() -- 这是 C++ 类的创建,我定义了一个静态函数 Create() self.CPlusClass:RegisterCallback(15, create_closure(self, "Callback")) end