C++实现对lua访问的封装

这是一个几年前写的对lua的访问封装,当时的项目仅提供了最基本的lua访问接口:调用lua函数,向lua注册标准格式的C++函数.

本来我想引进luabind,但luabind相对又过于复杂,并不是所有功能都是我需要的,并且还要为此引入庞大boost.最终还是决定

按需求编写一个简单的封装库.

首先简单列一下我的需求:

1)可以注册任意类型的C++函数到lua中

2)可以方便的调用lua函数,方便的访问lua中的表

3)可以访问lua中创建的对象,调用lua对象提供的方法

4)注册C++类型到lua,使lua可以访问C++对象的字段,和函数

下面介绍一下提供的一些API:

1)call_luaFunction,用于方便的调用lua函数,使用格式如下:

int ret = call_luaFunction<int>("funname",L);

2)register_function,用于向lua注册任意类型的C++函数,例如有如下函数:

static int showmsg(const char *msg)

{

  printf("%s\n",msg);

  return 0;

}

则可以这样注册,register_function(L,"show",showmsg);

3)register_class,register_property,register_member_function用于向lua注册一个C++类型

4)luaObject,代表lua中的对象,可以通过成员函数CallMemberFunction,SetMemberValue,GetMemberValue

访问lua对象的方法和成员变量

5)luatable,代表lua中的表

6)Interger64用以支持在lua中实现64位整型运算

这里说明一下,我不想C++对象在lua中被创建,而只能在C++中创建再传递给lua(Interger64是个例外,因为它主要是在lua中被使用的类型),所以register_class

并没有提供构造函数的注册.

测试代码:

  1 #include "luaWrapper.h"
  2 #include <stdio.h>
  3
  4 static int userdata(lua_State *L)
  5 {
  6     int *a = (int*)lua_touserdata(L,-1);
  7     printf("a = %d\n",*a);
  8     return 0;
  9 }
 10 static int showmsg(const char *msg)
 11 {
 12     printf("%s\n",msg);
 13     return 0;
 14 }
 15
 16 class testa
 17 {
 18 public:
 19     int vala;
 20     int valb[10];
 21 };
 22
 23 class testd
 24 {
 25 public:
 26     virtual void testdf(){}
 27     int vald;
 28 };
 29
 30 class testb : virtual public testa,virtual public testd
 31 {
 32 public:
 33
 34     virtual void function()
 35     {
 36         printf("this is function\n");
 37     }
 38
 39     int64_t valb;
 40     double  vald;
 41 };
 42
 43 class testc : public testb
 44 {
 45 public:
 46     void function()
 47     {
 48         printf("this is testc\n");
 49     }
 50
 51     void functionc()
 52     {
 53         printf("functionc\n");
 54     }
 55 };
 56
 57 int main()
 58 {
 59     luaWrapper lw;
 60     lw.init();
 61     lw.load("start.lua");
 62     lua_State *L = *(&lw);
 63     //测试注册任意C++函数
 64     register_function(L,"show",showmsg);
 65
 66     //测试向lua注册C++类
 67     register_class<testb>(L,"testb");
 68     register_property("valb",&testb::valb);
 69     register_property("vald",&testb::vald);
 70     register_member_function("func",&testb::function);
 71
 72     register_class<testc,testb>(L,"testc");
 73     register_member_function("funcc",&testc::functionc);
 74
 75     testc tc;
 76     tc.valb = 1000000000000000002;
 77     tc.vald = 10.0f;
 78     testb tb;
 79     tb.valb = 1000;
 80     call_luaFunction<void>("test1",L,&tc,(int64_t)1000000000000000001);
 81     printf("%lld\n",tc.valb);
 82     printf("%f\n",tc.vald);
 83
 84     luatable ret = call_luaFunction<luatable>("test2",L);
 85     int i=0;
 86     printf("{");
 87     for(;i<ret.size();++i)
 88     {
 89         printf("%d,",any_cast<int>(ret[i]));
 90     }
 91     printf("}\n");
 92
 93     lua_results<5> ret1 = call_luaFunction<lua_results<5>>("test4",L);
 94     printf("{");
 95     for(i=0;i<ret1._rets.size();++i)
 96     {
 97         printf("%d,",any_cast<int>(ret1._rets[i]));
 98     }
 99     printf("}\n");
100
101     luaObject ac = call_luaFunction<luaObject>("test3",L);
102     ac.CallMemberFunction<void>("show");
103     printf("balance:%d\n",ac.GetMemberValue<int>("balance"));
104     ac.SetMemberValue<int>("balance",1000);
105     printf("balance:%d\n",ac.GetMemberValue<int>("balance"));
106     luatable lt_in;
107     for(int i = 0; i < 5;++i)
108         lt_in.push_back(i);
109     call_luaFunction<void>("test5",L,lt_in);
110
111     call_luaFunction<void>("test6",L,"this is string");
112
113     lt_in.clear();
114     lt_in.push_back((const char*)"hello1");
115     lt_in.push_back((const char*)"hello2");
116     lt_in.push_back((const char*)"hello3");
117     lt_in.push_back((const char*)"hello4");
118     lt_in.push_back((const char*)"hello5");
119     call_luaFunction<void>("test5",L,lt_in);
120     getchar();
121     return 0;
122 }
 1 Account = {
 2 balance = 10,
 3 names=0,
 4 }
 5
 6
 7 function Account:withdraw (v)
 8       self.balance = self.balance - v
 9 end
10
11 function Account:new (o)
12   o = o or {}
13   setmetatable(o, self)
14   self.__index = self
15   return o
16 end
17
18 function Account:show()
19     print("this is account show")
20 end
21
22 function Account:getBalance()
23     return self.balance
24 end
25
26 function Account:setBalance(val)
27     self.balance = val
28 end
29
30 function t(tb)
31     tb:func()
32 end
33
34 function test1(tb,i)
35     t(tb)
36     show("hello world")
37     print(tb.valb)
38     tb.valb = i64:new(10000003)
39     tb.vald = 1000.2
40     print(i)
41 end
42
43 function test2()
44     return {1,2,3,4,5}
45 end
46
47 function test3()
48     account = Account:new();
49     account.balance = 100
50     account.name = "sniperHW"
51     return account
52 end
53
54 function test4()
55     return 1,2,3,4,5
56 end
57
58 function test5(lt)
59     print(lt[1])
60     print(lt[2])
61     print(lt[3])
62     print(lt[4])
63     print(lt[5])
64 end
65
66 function test6(str)
67     print(str)
68 end
时间: 2024-11-03 22:22:36

C++实现对lua访问的封装的相关文章

Java Web学习系列——Maven Web项目中集成使用Spring、MyBatis实现对MySQL的数据访问

本篇内容还是建立在上一篇Java Web学习系列——Maven Web项目中集成使用Spring基础之上,对之前的Maven Web项目进行升级改造,实现对MySQL的数据访问. 添加依赖Jar包 这部分内容需要以下Jar包支持 mysql-connector:MySQL数据库连接驱动,架起服务端与数据库沟通的桥梁: MyBatis:一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架: log4j:Apache的开源项目,一个功能强大的日志组件,提供方便的日志记录: 修改后的pom.xm

js 实现对ajax请求面向对象的封装

AJAX 是一种用于创建快速动态网页的技术.通过在后台与服务器进行少量数据交换,AJAX 可以使网页实现异步更新.这意味着可以在不重新加载整个网页的情况下,对网页的某部分进行更新. 在js中使用ajax请求一般包含三个步骤: 1.创建XMLHttp对象 2.发送请求:包括打开链接.发送请求 3.处理响应 在不使用任何的js框架的情况下,要想使用ajax,可能需要向下面一样进行代码的编写 var xmlHttp = xmlHttpCreate();//创建对象 xmlHttp.onreadysta

02-keepalived实现对nginx服务的高可用(主备)

实验环境:controller3,controller4为后端web服务器,controller1,controller2为nginx负载均衡服务器,用keepalived实现主备模式的高可用 controller1  IP:9.110.187.120 10.1.1.120 controller2  IP:9.110.187.121 10.1.1.121 controller3  IP:10.1.1.122 controller4  IP:10.1.1.123 1.controller3,con

jmeter通过BeanShell 脚本,实现对http请求参数的加密

jmeter一直是一款很好的接口和性能测试工具,它是开源的,不需要为此支付任何费用,而且可以下载源码,可以在修改源代码并在此基础上拓展自己的功能或插件,它可以跟ant和jenkins结合起来搭建自己的自动化接口测试框架.它的好还在于它是纯JAVA开发的,因此,它可以更好的跟JAVA对接,通过引入自己封装的jar文件,可以方便的实现对jmeter各种个性化需求的功能的拓展,下面以一个实际例子来说明jmeter怎么引入自己开发的java工具类来实现对http请求参数的加密处理. 在此之前,我们假设有

利用PRTG实现对cisco路由器的cpu负载、端口流量等的监控

一.实验目的及前期准备 用gns3.vmware模拟真实的环境,利用prtg实现对cisco路由器状态的监控 前期准备:GNS3仿真路由软件和VMware虚拟软件,PRTG. 二.实验步骤 1)搭建如下拓扑环境 VMware server有2张网卡,一张(out)桥接到真实主机(Windows7)的网卡,另一张(in)连接到GNS3的R1路由器的e1/0上:R1路由器的e1/1和VMwar winxp的网卡相连. a)VMware安装一个server2003系统和一个xp系统,并虚拟3张虚拟网卡

Cacti实现对linux和win监控

参考文章:http://coolner.blog.51cto.com/957576/689400 Cacti是一套基于PHP,MySQL,SNMP及RRDTool开发的网络流量监测图形分析工具. Cacti 是通过 snmpget来获取数据,使用 RRDtool绘画图形,而且你完全可以不需要了解RRDtool复杂的参数.它提供了非常强大的数据和用户管理功能,可以指定每一个用户能查看树状结 构.host以及任何一张图,还可以与LDAP结合进行用户验证,同时也能自己增加模板,功能非常强大完善.界面友

用myecplise自带工具实现对SSH框架整合

之前搭建ssh环境的,都是先要引入一堆jar包,一下没整明白就会出现jar包冲突的问题,在这里,我们使用myecplise自带的工具,实现jar包的依赖和配置文件的生成. 我们用的到的工具是:myecplise2014 第一步:新建一个web project 第一步:添加项目所依赖的jar包 1.添加struts所依赖的jar包 完成后,在src目录下可以发现struts.xml 2.添加spring所依赖的jar包 完成后,可以在src目录下发现applicationContext.xml 3

django结合mongoengine实现对mongodb的操作

1. 引言 以前一直是使用django+关系型数据库mysql进行开发,现在需要使用django+非关系型数据库mongodb,在django中可以直接运用ORM架构实现对mysql的操作,但是django不支持mongodb,这样我们就需要使用mongoengine这个模块来实现django model的封装 2. 前期准备 安装必要的模块mongoengine和pymongo(因为mongoengine依赖pymongo,所有先安装mongoengine,就会自动安装pymongo) # 因

zabbix监控安装及实现对tomcat服务器监控

一.zabbix监控安装配置实现对本机的监控 监控端ip 192.168.1.11 被监控端ip 192.168.1.12 1.zabbix相关包的安装 1)zabbix的仓库源配置 [email protected]:~# wget https://repo.zabbix.com/zabbix/4.0/ubuntu/pool/main/z/zabbix-release/zabbix-release_4.0-2+bionic_all.deb 2)安装zabbixx-release_4.0-2+b