我花了很多时间来让Lua与C++类一起工作.Lua比C++更像是一个C风格的API,但有很多方法可以将它与C++一起使用.
在Lua C API中,指针由userdata(或轻用户数据表示,它没有元表并且不是垃圾回收).Userdata可以与metatable相关联,它在Lua中有点像一个类.作为该元表的一部分的C函数包装了c ++类的方法,并充当Lua中的类的方法.
考虑具有私有成员名称(ac字符串)和年龄(int)的基本人员类.名称由构造函数设置,不能更改.年龄暴露于getter和setter:
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;
}
};
Run Code Online (Sandbox Code Playgroud)
为了首先将这个暴露给Lua,我将为符合lua_CFunction原型的所有方法编写包装函数,该原型将lua状态作为参数,并返回一个int,表示它推送到堆栈的值的数量(通常为1或0) ).
这些函数中最棘手的是构造函数,它将返回一个像对象一样的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;
}
Run Code Online (Sandbox Code Playgroud)
创建其他方法时,您只需记住第一个参数将始终是指向我们使用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;
}
Run Code Online (Sandbox Code Playgroud)
最后,在初始化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;
}
Run Code Online (Sandbox Code Playgroud)
并测试它...
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;
}
Run Code Online (Sandbox Code Playgroud)
还有其他方法可以在Lua中实现OO.本文介绍了替代方案:http: //loadcode.blogspot.com/2007/02/wrapping-c-classes-in-lua.html