我正在寻找一种在C ++和Lua之间来回传输变量地址的方法。例如,将对象从C ++传输到Lua并进行一些处理,然后将其传回C ++。
然而,问题是如何从Lua执行C ++函数或方法?或者需要解决方法吗?
如果可能,您是否可以添加一个代码段来向我展示它是如何完成的?
我知道我还没有完全理解整个画面,所以如果有什么不妥,请纠正我。
答案 0 :(得分:9)
我花了很多时间来让Lua与C ++类一起工作。 Lua比C ++更像是一种C风格的API,但有很多方法可以将它与C ++一起使用。
在Lua C API中,指针由userdata(或light userdata表示,它没有元表并且不是垃圾收集的)。 Userdata可以与metatable相关联,它在Lua中有点像一个类。作为该元表的一部分的C函数包装了c ++类的方法,并作为Lua中的类的方法。
考虑具有私有成员名称(c字符串)和年龄(int)的基本人员类。名称由构造函数设置,不能更改。年龄暴露于吸气剂和二传手:
class person
{
private:
const char* name;
int age;
public:
person(const char* n) {
name = strdup(n);
}
~person() {
free((void*)name);
}
void print() {
printf("%s is %i\n",name, age);
}
int getAge() {
return this->age;
}
void setAge(int a) {
this->age=a;
}
};
首先将这个暴露给Lua,我将为符合lua_CFunction原型的所有方法编写包装函数,该原型将lua状态作为参数,并返回一个int,表示它推送到堆栈的值的数量(通常一个或零)。
这些函数中最棘手的是构造函数,它将返回一个像对象一样的Lua表。为此,lua_newuserdata用于创建指向对象指针的指针。我将假设我们将在Lua init期间创建一个包含这些c函数的元表“Person”。此元表必须与构造函数中的userdata相关联。
// wrap the constructor
int L_newPerson(lua_State* L) {
//pointer to pointer
person **p = (person **)lua_newuserdata(L, sizeof(person *));
//pointer to person
*p = new person(lua_tostring(L, 1));
// associate with Person meta table
lua_getglobal(L, "Person");
lua_setmetatable(L, -2);
return 1;
}
当创建其他方法时,您只需记住第一个参数将始终是指向我们使用newPerson创建的指针的指针。为了从中获取C ++对象,我们只是从lua_touserdata(L,1)中取消引用返回;。
int L_print(lua_State* L) {
person** p = (person**) lua_touserdata(L, 1);
(*p)->print();
return 0;
}
int L_getAge(lua_State* L) {
person** p = (person**) lua_touserdata(L, 1);
lua_pushnumber(L, (*p)->getAge());
return 1;
}
int L_setAge(lua_State* L) {
person** p = (person**) lua_touserdata(L, 1);
(*p)->setAge(lua_tonumber(L, 2));
return 0;
}
最后在初始化Lua期间使用luaL_register设置Person元表。
// our methods...
static const luaL_Reg p_methods[] = {
{"new", L_newPerson},{"print", L_print},
{"getAge", L_getAge},{"setAge", L_setAge},
{NULL, NULL}
};
lua_State* initLuaWithPerson() {
lua_State* L=lua_open();
luaL_openlibs(L);
luaL_register(L, "Person", p_methods);
lua_pushvalue(L,-1);
lua_setfield(L, -2, "__index");
return L;
}
并测试它......
const char* Lua_script =
"p1=Person.new('Angie'); p1:setAge(25);"
"p2=Person.new('Steve'); p2:setAge(32);"
"p1:print(); p2:print();";
int main() {
lua_State* L=initLuaWithPerson();
luaL_loadstring(L, Lua_script);
lua_pcall(L, 0, 0, 0);
return 0;
}
还有其他方法可以在Lua中实现OO。本文介绍了替代方案: http://loadcode.blogspot.com/2007/02/wrapping-c-classes-in-lua.html
答案 1 :(得分:4)
请参阅Lua用户wiki关于binding code to Lua的文章。有几种技术可以使C ++对象在围栏的Lua一侧变得有用,其复杂程度不仅仅是让Lua持有一个不能直接使用的不透明指针,而是完全包装暴露所有C ++方法,甚至可能允许用Lua编写的方法扩展的对象。
对于用C编写的简单函数库,使用Lua API手动编写自己的绑定来在Lua堆栈和库函数之间移动是相当容易的。
对于基于对象的系统,手动完成的工作要多得多,因此该页面上列出的一种绑定工具将使您的生活更加轻松。
答案 2 :(得分:2)
我不确定这是否是您正在寻找的但是您尝试过 luabind?
也许this question也有帮助。