马上面临毕业设计,打算做点跟网游有关的,先从做周边工具开始,目前正在做一个协议序列化和反序列化的东西,广告一波先: 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++的更多相关文章

  1. 黑马毕向东Java基础知识总结

    Java基础知识总结(超级经典) 转自:百度文库 黑马毕向东JAVA基础总结笔记    侵删! 写代码: 1,明确需求.我要做什么? 2,分析思路.我要怎么做?1,2,3. 3,确定步骤.每一个思路部 ...

  2. 《果壳中的C# C# 5.0 权威指南》 - 学习笔记

    <果壳中的C# C# 5.0 权威指南> ========== ========== ==========[作者] (美) Joseph Albahari (美) Ben Albahari ...

  3. Lua中调用C函数(lua-5.2.3)

    Lua能够调用C函数的能力将极大的提高Lua的可扩展性和可用性. 对于有些和操作系统相关的功能,或者是对效率要求较高的模块,我们全然能够通过C函数来实现,之后再通过Lua调用指定的C函数. 对于那些可 ...

  4. C程序与Lua脚本相互调用

    Lua脚本是一种可用于C程序开发/测试的工具,本篇介绍一下C程序与Lua脚本如何进行相互调用,更加详细的操作参见<Programing in Lua>.本文分为3个部分:1.Windows ...

  5. Win7 64位 VS2013环境编译Lua5.3.1

    主要参考这篇文章,原文有几个错误顺便改正了. 在Windows下使用Visual Studio编译Lua5.3 写本文时Lua官方网站放出的新版本为5.3.1,然后我不知道为啥,神奇的国内不能访问Lu ...

  6. lua如何调用C++函数

    第一步是定义函数.所有在Lua中被调用的C/C++函数将使用下面一类指针进行调用: typedef int (*lua_CFunction) (lua_State *L); 换句话说,函数必须要以Lu ...

  7. vs如何在C++中调用Lua

    最近Cocos2dx的学习卡壳了,一般的照抄代码我不想写上来,但想示例也想得我头晕...为了放松大脑调整状态于是开始学习Lua.Lua的语法学习还是比较简单的,学过javascript或者vbscri ...

  8. vs2013如何在C++中调用Lua(二)

    Lua学习笔记 vs2013如何在C++中调用Lua (此为转载教程) 本人试过完全可行 一.准备工作 1.下载Lua源码,地址:http://www.lua.org/download.html(我用 ...

  9. LUA脚本调用C场景,使用C API访问脚本构造的表

    LUA调用C lua解析中集成了一些系统服务, 故脚本中可以访问系统资源, 例如, lua脚本可以调用文件系统接口, 可以调用数学库, 但是总存在一些lua脚本中访问不到的系统服务或者扩展功能, 如果 ...

随机推荐

  1. CF Covered Path (贪心)

    Covered Path time limit per test 1 second memory limit per test 256 megabytes input standard input o ...

  2. LeetCode 203

    Remove Linked List Elements Remove all elements from a linked list of integers that have value val. ...

  3. 2012蓝桥杯C组本科决赛答案

    题目: 脱氧核糖核酸即常说的DNA,是一类带有遗传信息的生物大分子.它由4种主要的脱氧核苷酸(dAMP.dGMP.dCMT和dTMP)通过磷酸二酯键连接而成.这4种核苷酸可以分别记为:A.G.C.T. ...

  4. mac下的常用操作

    打开 应用程序(command+shift+A)-实用工具-终端 open .    直接打开Macintosh系统目录 其他口令(与linux一样)ls                显示当前目录内 ...

  5. html,css所遇问题(一)

    html,css所遇问题(一) div中添加背景图片必须设置宽高 例如:下述代码没有设置icon的宽高值,那么网页中也不会显示出背景图片,因为div 里面有内容才会出现背景,没内容又没设置宽高,那di ...

  6. MyBatis(3.2.3) - One-to-many mapping

    In the sample domain model, a tutor can teach one or more courses. This means that there is a one-to ...

  7. Agile.Net 组件式开发平台 - 权限管理组件

    RBAC原则       (1)最小权限原则之所以被RBAC所支持,是因为RBAC可以将其角色配置成其完成任务所需要的最小的权限集.       (2)责任分离原则可以通过调用相互独立互斥的角色来共同 ...

  8. 重叠I/O之可等待的重叠I/O【系列一】

    一 什么是异步I/O 同步I/O和异步I/O的关键不同就是在发出I/O请求后,线程是否会阻塞.当线程发出一个设备I/O请求的时候,线程会被挂起来,直到设备完成I/O请求为止,这称之为同步I/O.而对于 ...

  9. windows7下系统保护中出现错误“文件名、目录名或卷标语法不正确。(0x8007007B)“ 以及保护设置列表中出现“Windows7_os(c:)(找不到)”选项时的解决方法

    windows7下系统保护功能很是鸡肋,有事会出现一下两个问题: 1.出现错误“文件名.目录名或卷标语法不正确.(0x8007007B) 2.保护设置列表中出现“Windows7_os(c:)(找不到 ...

  10. iOS 9 之后更改状态栏字体颜色

    设置statusBar的[前景部分] 简单来说,就是设置显示电池电量.时间.网络部分标示的颜色, 这里只能设置两种颜色: 默认的黑色(UIStatusBarStyleDefault) 白色(UISta ...