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

    X264版本: 2004/06/03 函数作用: 将编码该宏块所需的信息加载到mb.pic.mb.cache两个结构体中,记录相邻宏块的存在性. 函数过程: 初始化坐标信息,这些坐标信息将在下面用作下 ...

  2. Dubbo认识

    Dubbo提供了服务注册.RPC服务调用.调用均衡.服务监控和服务failover等功能 Dubbo框架中有两个重要角色:(服务)提供者和(服务)消费者,这里为了简单起见,将包含了dubbo提供者或消 ...

  3. Angular2 从0到1 (二)

    第一节:Angular2 从0到1 (一)第三节:Angular2 从0到1 (三)第四节:Angular2 从0到1 (四) 作者:王芃 wpcfan@gmail.com 第二节:用Form表单做一 ...

  4. sublime安装 less环境

    工具的选择: mac-codekit simpless->跨平台 winless-windows  less.js下载:http://pan.baidu.com/s/1o60yTZ0   安装L ...

  5. css3 盒模型记

    css3 盒模型 css假定每个元素都会生成一个或多个矩形框,这称为元素框.各元素框中心有一个内容区.这个内容区周围有可选的内边距,边框和外边距.这些项之所以被认为是可选的,原因是它们的宽度可以设置为 ...

  6. Table of Contents - JAXB

    Getting Started Hello World Hello World with Namespace xjc - 将 XML Schema 编译成 Java 类 wsimport: 编译 WS ...

  7. .NET微信支付(H5仅限公众号支付)

    闲来无事,恰好有一个要用微信公众平台支付的功能,研究来研究去,就是要细心和多看腾讯提供的文档.当然有几个坑是很有必要说明一下的 公众号支付,这里统一叫H5支付,以下都是. 在做H5支付的时候,第一步就 ...

  8. C#_简单Excel导入

    引用程序集 Microsoft.Office.Core Microsoft.Office.Interop.Excel using System; using System.Collections.Ge ...

  9. 理解CPU内存管理

    概述:从设计层面理解CPU的内存模式,包括段式内存管理.页式内存管理以及虚拟化扩展内存管理.实际上,硬件支持与软件实现从来就不是能分开讲的,比如,Intel CPU架构师在选择CPU的硬件特性时,必然 ...

  10. Oracle 简介 三层结构

    引言: 主流数据库:sql server, oracle, my sql,IBM公司的DB2 ,oracle占有量很大 dbms(database management system)数据库管理系统 ...