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脚本中访问不到的系统服务或者扩展功能, 如果 ...
随机推荐
- linux-统计行数
wc -l ls |wc -l 查看文件夹下的行数 cat/less/more +文件名|wc -l
- [改善Java代码]由点及面,一叶知秋----集合大家族
Java中的集合类实在是太丰富了,有常用的ArrayList.HashMap,也有不常用的Stack. Queue,有线程安全的Vector.HashTable,也有线程不安全的LinkedList. ...
- [改善Java代码]异步运算考虑使用Callable接口
多线程有两种实现方式: 一种是实现Runnable接口,另一种是继承Thread类,这两种方式都有缺点,run方法没有返回值,不能抛出异常(这两个缺点归根到底是Runable接口的缺陷,Thread也 ...
- 写css动画
<!doctype html><html lang="en"> <head> <meta charset="UTF-8" ...
- trigger,triggerhandler模拟事件
常用模拟 有时候,需要通过模拟用户操作,来达到单击的效果.例如在用户进入页面后,就触发click事件,而不需要用户去主动单击. 在JQuery中,可以使用trigger()方法完成模拟操作.例如可以使 ...
- HTTP - 条件请求
当 HTTP 请求包含 If-XXX 这种样式的首部时,服务器会对附带的条件进行判断,只有判断指定条件为真,才会执行请求.这样的请求首部有五个,分别是 If-Modified-Since.If-Unm ...
- Annotation注解与butterknife
注解分为三种,一般来讲我们使用的是运行时会加载及能够反射读取的注解类型, 其他编译器生效的类型和编译后放入类文件而运行期不能加载解析的对我们没啥用. 所以从普通理解上来看,注解要配合着反射用就好了. ...
- Android从imageview中获得bitmap
第一种: 使用setDrawingCacheEnabled()和getDrawingCache()这两种方法,第一个是为了设置是否开启缓存,第二个就可以直接获得imageview中的缓存,一般来说需要 ...
- 169. Majority Element My Submissions Question
Total Accepted: 95925 Total Submissions: 239241 Difficulty: Easy Given an array of size n, find the ...
- Swift项目开发实战-基于分层架构的多版本iPhone计算器-直播公开课
Swift项目开发实战-基于分层架构的多版本iPhone计算器-直播公开课 本课程采用Q Q群直播方式进行直播,价值99元视频课程免费直播.完整的基于Swift项目实战,手把手教你做一个Swift版i ...