Lua 中的面向对象编程从 C 语言实现
2016-5-21 2:46:55
收藏:0
阅读:107
评论:2
我想在我的 Lua 解释器中实现面向对象编程。我知道可以从 C 函数返回 Lua 表。而且我希望返回的表格中充满了 C 函数。
player = getClosestPlayer();
player.walkTo();
其中 getClosestPlayer() 和 walkTo() 都是 C 函数。
从 walkTo() 的 C 函数中,如何区分类型?
我希望每个对象都有一个 gid,以便我可以使用它来标识对象 (player.gid),但我如何从 c 函数中访问该 gid?
换句话说,如何在 C 代码中实现相当于 self.gid 的功能?
int l_playerWalkTo(lua_State* functionState){
int gid = // self.gid?
// do something with gid
}
我可以使用一个 upvalue 来为表中的每个函数提供上下文,但是否有更优雅的方法来实现呢?
点赞
用户5624167
感谢 macroland 的回答,我只是想澄清一下他所说的。 这个 Lua 包装器可以用于将 C++ 类实现到 Lua 中: https://bitbucket.org/alexames/luawrapper/overview
使用这个库的一个很好的例子可以在这里找到: https://bitbucket.org/alexames/luawrapperexample/src/
这是代码(直接从示例网站中拿的):
Lua:
alicesaccount = BankAccount.new("Alice", 100)
alicesaccount:deposit(20);
alicesaccount:deposit(30);
alicesaccount:deposit(40);
C++:
BankAccount* BankAccount_new(lua_State *L)
{
const char* owner = luaL_checkstring(L, 1);
float balance = luaL_checknumber(L, 2);
return new BankAccount(owner, balance);
}
int BankAccount_deposit(lua_State *L)
{
BankAccount* account = luaW_check<BankAccount>(L, 1);
float amount = luaL_checknumber(L, 2);
account->deposit(amount);
return 0;
}
static luaL_Reg BankAccount_table[] =
{
{ NULL, NULL }
};
static luaL_Reg BankAccount_metatable[] =
{
{ "deposit", BankAccount_deposit },
{ NULL, NULL }
};
int luaopen_BankAccount(lua_State* L)
{
luaW_register<BankAccount>(L,
"BankAccount",
BankAccount_table,
BankAccount_metatable,
BankAccount_new // 如果您的类有默认构造函数,可以省略此参数,
// LuaWrapper 会为您生成一个默认的分配器。
);
return 1;
}
正如您看到的,使用这种方法,第一个参数是对象的实例。
2016-05-21 11:01:13
评论区的留言会收到邮件通知哦~
推荐文章
- 如何将两个不同的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中获取用户配置主目录的跨平台方法
我有类似的问题,解决的方法是:
1)在C++中创建一个抽象方法的接口类
class LuaInterfaceOOP { public: LuaInterfaceOOP(){} virtual CObject* clone(void) const=0; virtual wxString type(void)=0; virtual wxString ToString(void)=0; wxString GetType()return this->type(); wxString GetToString() return this->ToString(); virtual ~CObject(){} };2)任何你想要在Lua中使用的类都应该实现这个接口,以保持一致性
class MyClass: public LuaInterfaceOOP { public: wxString type() { return "MyClass";} wxString ToString(); };3)当你为这个类写一个包装器的时候,确保
int MyClass_toString(lua_State* L) { MyClass* mc= luaW_check<MyClass>(L, 1); const char* str=mc->ToString().c_str(); lua_pushstring(L, str); return 1; } int MyClass_type(lua_State* L) { lua_pushstring(L,"MyClass"); return 1; }4)重载Lua提供的type函数,对你来说最重要的部分将是:
case LUA_TUSERDATA: { wxString str1; if(lua_getmetatable(L,idx)) // Stk: Userdata Table { lua_getfield(L,-1,"type"); // Stk: Userdata Table function if(!lua_pcall(L,0,1,0)) // Stk: Userdata Table string { str1<<lua_tostring(L,-1); wxReturnStr<<str1; lua_pop(L,2);// Stk: Userdata } else //stk: Userdata table { lua_pop(L,1); wxReturnStr<<"userdata"; //stk: Userdata } }else wxReturnStr<<"userdata"; break; }编辑1:添加将C++函数包装到Lua的代码
static luaL_Reg MyClass_table[] = { { NULL, NULL } }; static luaL_Reg Myclass_metatable[] = { {"type", Myclass_type}, {"__tostring", Myclass_toString}, { NULL, NULL } };最后,
static int luaopen_MyClass(lua_State* L) { luaW_register<MyClass>(L, "MyClass", MyClass_table, MyClass_metatable, MyClass_new); return 1; }现在在Lua中,你可以使用诸如
if(type(aclass)=="MyClass")这样的表达式。我不确定这些步骤是否是最好的方式,但到目前为止它起作用了。