Lua的C++绑定库(一)

C++是一门非常复杂的语言,然而更可怕的是,这门语言的各种奇葩特性还在继续增加,很多C++的程序员都会觉得这完全是在给自己添堵嘛,都已经这么复杂了,何必还要使劲往里面塞东西呢,明明C++03或者说是C++98的标准就已经完全够用了。我个人的看法呢,其实后续的标准还是很有必要的,因为这里面的很多新标准,对于一些写底层库的作者来说,真的是非常需要,换句话说,如果没有type_traits、右值语义、可...
摘要由CSDN通过智能技术生成

C++是一门非常复杂的语言,然而更可怕的是,这门语言的各种奇葩特性还在继续增加,很多C++的程序员都会觉得这完全是在给自己添堵嘛,都已经这么复杂了,何必还要使劲往里面塞东西呢,明明C++03或者说是C++98的标准就已经完全够用了。我个人的看法呢,其实后续的标准还是很有必要的,因为这里面的很多新标准,对于一些写底层库的作者来说,真的是非常需要,换句话说,如果没有type_traits、右值语义可变参数模板这些特性,那我就不会重新造这个轮子,也就不会写这篇文章了,正是因为C++11的标准里面引入了这些特性,以往一些库的实现就显得很笨重、很复杂,所以我决定重新造一个代码轻量级但是功能却不会有删减的轮子。最后,友情提示那些反感C++新标准的小伙伴一下,其实这些新标准里面大部分的内容我们根本就不必关心,因为对于写逻辑层的功能来说,这些功能我们根本就用不上,能用上的也就一些新增的语法糖,例如auto、foreach、lambda,其它的功能有个毛用啊,不过呢,这些语法糖还是建议了解一下,可以省很多事哦。

我个人最早接触的lua绑定库是ELuna,它是由我的一个同事引入项目中的,并且以此为基础进行了大量魔改操作,然后当我接手这个代码的时候,可读性有点伤人。我后来又在网上搜了一下,感觉luatinker这个库评价挺好的,于是我就想在项目里引入luatinker。可惜的是,luatinker是基于lua5.1写的,而当时lua5.3已经出来了,大家都知道,lua5.3是原生支持64位整数的,而在这之前,所有的lua绑定库为了支持64位整数,都得用一些奇葩手段才能简单支持,最重要的是,我有把64位整数传入脚本的需求,所以只好先做移植了,好不容易移植过去了,写了几个例子一跑,惨了,有bug啊。好吧,那就继续改吧,等这些都做完了,静下来想了想,好像对于这个luatinker自己已经完全掌握了,而且这个库里面还有好多代码是c++11已经原生支持了的,干脆我自己用c++11实现一份吧,这样子代码肯定简洁的多,代码写得越少,bug也就写得越少嘛。所以总结就一句话,以下这个库的api设计跟luatinker几乎完全一致,只要你用过luatinker,那么用这个库,基本上是0成本,除非是luatinker缺失的功能。

好了,开始进入正题。我魔改过的luatinker:https://github.com/jallyx/LuaTinker,新轮子:https://gitee.com/jallyx/fusion/tree/master/src/lua。友情提示,std::string_view是c++17引入的,所以c++11编译这个代码需要先自己处理一下,方案1、删掉这个功能,具体做法就是哪儿编译出错就删哪儿,方案2、使用boost提供的boost::string_view或boost::string_ref,然后这样包装一下https://gitee.com/jallyx/fusion/blob/master/feature/string_view,方案3、使用c++17吧。

让我们先从luatinker的例子走起。

 1 #include "lua/LuaFunc.h"
 2 
 3 int cpp_func(int arg1, int arg2) {
 4     return arg1 + arg2;
 5 }
 6 
 7 const char *lua_str = R"(
 8     print('cpp_func(1,2) = ' .. cpp_func(1, 2)) --调用c++全局函数
 9     function lua_func(arg1, arg2) --定义lua全局函数
10         return arg1 + arg2
11     end
12 )";
13 
14 int main(int argc, char **argv)
15 {
16     lua_State *L = lua::open();  // 新建lua虚拟机,并做一些必要的初始化工作。
17     lua::def(L, "cpp_func", cpp_func);  // 向lua注册c++全局函数
18     lua::dostring(L, lua_str);  // 执行lua脚本,如果是文件则需要调用lua::dofile。
19     printf("lua_func(3,4) = %d\n", LuaFunc(L, "lua_func").Call<int>(3, 4));  // 调用lua的全局函数
20     lua::close(L);  // 关闭lua虚拟机,释放资源
21     return 0;
22 }

程序输出:

cpp_func(1,2) = 3
lua_func(3,4) = 7

 似乎太简单了,我都不知道需要解释点啥,接下来进入第二个例子。

 1 #include "lua/LuaBus.h"
 2 
 3 static int cpp_int = 100;
 4 
 5 const char *lua_str = R"(
 6     print('cpp_int = ' .. cpp_int) -- 打印c++的全局变量
 7     lua_int = 200 -- 定义lua的全局变量
 8 )";
 9 
10 int main(int argc, char **argv)
11 {
12     lua_State *L = lua::open();  // 新建lua虚拟机,并做一些必要的初始化工作。
13     lua::set(L, "cpp_int", cpp_int);  // 向lua注册c++全局变量
14     lua::dostring(L, lua_str);  // 执行lua脚本,如果是文件则需要调用lua::dofile。
15     printf("lua_int = %d\n", lua::get<int>(L, "lua_int"));  // 获取lua的全局变量
16     lua::close(L);  // 关闭lua虚拟机,释放资源
17     return 0;
18 }

程序输出:

cpp_int = 100
lua_int = 200

 第三个例子,稍微有点复杂,主要是对c++类成员函数、成员变量、类继承的支持。在最后的lua代码中,对用到的c++类变量进行了一个内省输出的操作,如果大家对自己的定位是这个库的使用者,则完全没必要关心。PS:我写这段代码也只是因为luatinker的测试代码是这样的而已。

 1 #include "lua/LuaBus.h"
 2 
 3 struct A {
 4     A(int v) : value(v) {}
 5     int
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值