lua5.3调用C/C++
马上面临毕业设计,打算做点跟网游有关的,先从做周边工具开始,目前正在做一个协议序列化和反序列化的东西,广告一波先: https://github.com/Anti-Magic/rproto
目前非常简陋,功能还没做完,不要当真。。
因为目标是绑定到lua,作为一个独立的库,不想对项目有依赖,这样的好处是客户端和服务端都可以方便的拿来用,所以打算手动绑定。
我夜观天象发现,到目前为止网上找不到针对lua5.3的这么简明扼要且完整的示例,转载注明出处:http://www.cnblogs.com/wolfred7464/p/5147675.html
由于lua提供的require函数可以引入C语言的动态链接库,对于使用者来说,不需配置,只要调用require就可以,肯定是最简单的方法。(其实iOS不能这样做的,唉,习惯就好)
首先读者需要对lua提供的操作虚拟栈的函数比较熟悉,不熟悉的先翻手册吧:http://cloudwu.github.io/lua53doc/manual.html
先上一段简单的示例,功能是使用C语言编写一个计算2个浮点数之和的add函数,绑定到lua由lua调用:
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
#include "luaconf.h" double add(double x, double y) {
return x+y;
} static int ladd(lua_State* L) {
double x = luaL_checknumber(L, );
double y = luaL_checknumber(L, );
lua_pushnumber(L, add(x+y));
return ;
} int luaopen_xxx(lua_State* L) {
luaL_checkversion(L); struct luaL_Reg funcs[] = {
{"add", ladd},
{NULL, NULL}
};
luaL_newlib(L, funcs);
return ;
}
在linux使用gcc编译:
gcc main.c -shared -fPIC -I/usr/local/include -o xxx.so
lua的package.cpath中需要能搜索到我们的so,设置cpath的方法网上搜一下有很多。然后lua代码中这样调用:
local xxx = require "xxx"
print(xxx.add(, ))
最后在终端执行:
lua test.lua
这个例子就跑起来了,虽然步骤说不上多简单,但是足够清晰吧。。为了简单,我就不写检查参数数量和类型是否匹配的代码了,后面的例子也是。
如何使用lua调用C++呢?只要你会操作userdata,基本上照搬上面的C语言的方式就可以,只不过显式传递C++的this指针就可以。再上一个简单的代码:
#include <lua.hpp>
class TTT {
public:
TTT() {}
~TTT() {}
double add(double x, double y) {
return x+y;
}
};
extern "C"
{
static int lnewTTT(lua_State* L) {
TTT** p = (TTT**)lua_newuserdata(L, sizeof(TTT*));
*p = new TTT();
return ;
}
static int ldelTTT(lua_State* L) {
TTT** p = (TTT**)lua_topointer(L, );
delete *p;
*p = nullptr;
return ;
}
static int ladd(lua_State* L) {
TTT** p = (TTT**)lua_topointer(L, );
TTT* pt = *p;
lua_pushnumber(L, pt->add(lua_tonumber(L, ), lua_tonumber(L, )));
return ;
}
int luaopen_xxx(lua_State* L) {
luaL_checkversion(L);
luaL_openlibs(L);
struct luaL_Reg funcs[] = {
{"new", lnewTTT},
{"add", ladd},
{"del", ldelTTT},
{NULL, NULL}
};
luaL_newlib(L, funcs);
return ;
}
}
local xxx = require "xxx"
local t = xxx.new()
print(xxx.add(t, , ))
xxx.del(t)
(为什么要使用指针的指针呢?因为lua申请内存和释放内存时不会调用C++的构造函数和析构函数,我们又不能手动去调用,只能使用指针的指针,便于手动调用构造和析构函数了。)
使用lua的userdata保存this指针,然后作为参数传递到绑定函数,然后C语言就可以调用了,第一个例子明白后,这个没什么难度。
但是这样做有三个问题:一是无法检查lua传来的this指针是否是正确的类型,二是需要手动释放内存,三是lua代码中调用起来太麻烦。
这三个问题有一个共同的解决方案:元表(metatable)。
1、给同一类userdata设置同一个元表,利用元表就可以区别不同类型的userdata。
2、lua垃圾回收时会调用元表中的"__gc"元方法,我们可以利用这个元方法析构C++对象。
3、索引字段会调用"__index"方法,不存在这个方法时会从元表中查找,利用这个特性我们可以把red.add(t, x, y)这样的调用变成t.add(t, x, y),然后就可以写成t:add(x, y)了。
把第二个例子中的lnewTTT和luaopen_xxx两个函数修改一下就可以,上代码:
static int lnewTTT(lua_State* L) {
TTT** p = (TTT**)lua_newuserdata(L, sizeof(TTT*));
*p = new TTT();
luaL_getmetatable(L, "xxx.TTT");
lua_setmetatable(L, -);
return ;
}
int luaopen_xxx(lua_State* L) {
luaL_checkversion(L);
luaL_openlibs(L);
struct luaL_Reg funcs[] = {
{"new", lnewTTT},
{NULL, NULL}
};
struct luaL_Reg funcs_meta[] = {
{"add", ladd},
{NULL, NULL}
};
luaL_newmetatable(L, "xxx.TTT");
lua_pushstring(L, "__gc");
lua_pushcfunction(L, ldelTTT);
lua_settable(L, -);
lua_pushstring(L, "__index");
lua_pushvalue(L, -);
lua_settable(L, -);
luaL_setfuncs(L, funcs_meta, );
luaL_newlib(L, funcs);
return ;
}
local xxx = require "xxx"
local t = xxx.new()
print(t:add(, ))
基本上就是这样了,绑定其他的数据类型,或者保存上下文等,都可以查找手册解决,lua天生为了嵌入宿主语言而设计,与C语言的交互有天然的优势。
lua5.3调用C/C++的更多相关文章
- 黑马毕向东Java基础知识总结
Java基础知识总结(超级经典) 转自:百度文库 黑马毕向东JAVA基础总结笔记 侵删! 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部 ...
- 《果壳中的C# C# 5.0 权威指南》 - 学习笔记
<果壳中的C# C# 5.0 权威指南> ========== ========== ==========[作者] (美) Joseph Albahari (美) Ben Albahari ...
- Lua中调用C函数(lua-5.2.3)
Lua能够调用C函数的能力将极大的提高Lua的可扩展性和可用性. 对于有些和操作系统相关的功能,或者是对效率要求较高的模块,我们全然能够通过C函数来实现,之后再通过Lua调用指定的C函数. 对于那些可 ...
- C程序与Lua脚本相互调用
Lua脚本是一种可用于C程序开发/测试的工具,本篇介绍一下C程序与Lua脚本如何进行相互调用,更加详细的操作参见<Programing in Lua>.本文分为3个部分:1.Windows ...
- Win7 64位 VS2013环境编译Lua5.3.1
主要参考这篇文章,原文有几个错误顺便改正了. 在Windows下使用Visual Studio编译Lua5.3 写本文时Lua官方网站放出的新版本为5.3.1,然后我不知道为啥,神奇的国内不能访问Lu ...
- lua如何调用C++函数
第一步是定义函数.所有在Lua中被调用的C/C++函数将使用下面一类指针进行调用: typedef int (*lua_CFunction) (lua_State *L); 换句话说,函数必须要以Lu ...
- vs如何在C++中调用Lua
最近Cocos2dx的学习卡壳了,一般的照抄代码我不想写上来,但想示例也想得我头晕...为了放松大脑调整状态于是开始学习Lua.Lua的语法学习还是比较简单的,学过javascript或者vbscri ...
- vs2013如何在C++中调用Lua(二)
Lua学习笔记 vs2013如何在C++中调用Lua (此为转载教程) 本人试过完全可行 一.准备工作 1.下载Lua源码,地址:http://www.lua.org/download.html(我用 ...
- LUA脚本调用C场景,使用C API访问脚本构造的表
LUA调用C lua解析中集成了一些系统服务, 故脚本中可以访问系统资源, 例如, lua脚本可以调用文件系统接口, 可以调用数学库, 但是总存在一些lua脚本中访问不到的系统服务或者扩展功能, 如果 ...
随机推荐
- JavaScript的正则表达式使用
一:遇到问题 今天做项目时,在前台js对身份证号进行验证时,一直达不到预期的效果,我是监控文本域变量, $scope.watch('form.idNo',function(v){ if(!v){ re ...
- Oracle procedure 基本语法
转自:http://lorry1113.javaeye.com/blog/513851 关键字: oracle 存储过程 1.基本结构 CREATE OR REPLACE PROCEDURE 存储过程 ...
- 汇总#pragma用法
这几天忙着去复习了,但是心理总是不踏实,不到实验室里就觉得一天的生活变了个样,现在还是晚上来这里“搞起”吧,白天还是在复习准备考试.因为要开始学习freescale,准备明年的比赛了,觉得是时候开始搞 ...
- Mina的线程模型
在Mina的NIO模式中有三种I/O工作线程(这三种线程模型只在NIOSocket中有效,在NIO数据包和虚拟管道中没有,也不需要配置): IoAcceptor/IoConnector线程 IoPro ...
- hdu 4267 树形DP
思路:先dfs一下,找出1,n间的路径长度和价值,回溯时将该路径长度和价值清零.那么对剩下的图就可以直接树形dp求解了. #include<iostream> #include<al ...
- Codevs 3729==洛谷P1941 飞扬的小鸟
P1941 飞扬的小鸟 456通过 2.4K提交 题目提供者该用户不存在 标签动态规划2014NOIp提高组 难度提高+/省选- 提交该题 讨论 题解 记录 题目描述 Flappy Bird 是一 ...
- java按行读取txt并按行写入
IO流想必大家都很熟悉了,本次实现的需求是按行读取文件内容并且按行写入,代码如下: try { String encoding="utf-8"; //设定自己需要的字符编码集 Fi ...
- Quartz Scheduler(2.2.1) - Usage of JobDataMap
The JobDataMap can be used to hold any amount of (serializable) data objects which you wish to have ...
- Networking - ICMP 协议
发送到远程计算机的数据通常发经过一个或多个路由器,这些路由器在把数据传输到最终目的地的过程中可能发生多种问题.路由器利用 ICMP 把问题通知给源 IP.ICMP 还有用于其他调试和排错的功能. IC ...
- 使用ptrace向已运行进程中注入.so并执行相关函数
这个总结的很好,从前一个项目也用到这中技术 转自:http://blog.csdn.net/myarrow/article/details/9630377 1. 简介 使用ptrace向已运行进程中注 ...