引言

上篇文章我们学习了C如何调用Lua,今天我们就来聊聊Lua 如何调用C。

Lua版本:Lua 5.3.5

对于Lua提供的接口有不清楚的,可以参考Lua接口官方文档

一、Lua调用C步骤

  1. 需要将C文件编译成动态库
  2. 在Lua文件中使用package.cpath配置C动态库路径
  3. 使用require 关键字引入指定C文件

因为Lua只认识.so文件,会去识别以 luaopen_* 开头的函数执行。

二、代码示例

2.1 lua 通过调用C中的方法将自己参数打印到终端

Lua源文件 test-tbl.lua

package.cpath = "./?.so" --c库的路径local so = require "tbl.c"  -- 这里xxx.c  对应 xxx.so 动态库so.echo("hello world") -- 新的虚拟栈
so.echo("hello world1")-- 新的虚拟栈
so.echo("hello world2")-- 新的虚拟栈

C源文件 lua-tbl.c

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdio.h>static int
lecho (lua_State *L) {const char* str = lua_tostring(L, -1);fprintf(stdout, "%s\n", str);return 0;
}static const luaL_Reg l[] = {// 导出给lua使用数组{"echo", lecho},{NULL, NULL},
};int
luaopen_tbl_c(lua_State *L) { // local tbl = require "tbl.c"// 创建一张新的表,并预分配足够保存下数组 l 内容的空间luaL_newlib(L, l);return 1;
}

编译 lua-tbl.c 文件为动态库:

gcc  lua-tbl.c -fPIC -shared -o  tbl.so -Wall

就会在当前目录会生成 tbl.so 文件,执行 lua test-tbl.lua
运行结果:

2.2 userdata 实战应用

Lua源文件 test-ud.lua

package.cpath = "./?.so"
local so = require "ud.c"local ud = so.new()ud:echo("hello world1")
ud:again()
ud:echo("hello world2")
ud:again()
ud:echo("hello world3")
ud:again()
--./lua/src/lua test-ud.lua

C源文件 lua-ud.c

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>#include <stdio.h>
#include <stdlib.h>
#include <string.h>struct log {int count;
};static int
lagain(lua_State *L) {struct log *p = (struct log *)luaL_checkudata(L, 1, "mk.ud.log");lua_getuservalue(L, -1);const char* str = lua_tostring(L, -1);fprintf(stdout, "ud[n=%d]----%s\n", p->count, str);return 0;
}static int
lecho(lua_State *L) {/*void *luaL_checkudata (lua_State *L, int arg, const char *tname);检查arg是不是userdata类型,如果是 返回userdata的内存地址*/struct log *p = (struct log *)luaL_checkudata(L, 1, "mk.ud.log");const char* str = lua_tostring(L, -1);p->count++;// Pops a value from the stack and sets it as the new n-th user value associated to the full userdata at the given index. Returns 0 if the userdata does not have that value.lua_setuservalue(L, -2);fprintf(stdout, "ud[n=%d]----%s\n", p->count, str);return 0;
}static int
lnew (lua_State *L) {struct log *q = (struct log*)lua_newuserdata(L, sizeof(struct log));q->count = 0;lua_pushstring(L, "");lua_setuservalue(L, -2);// 如果key(mk.ud.log) 存在,返回0; 否则为userdata创建一个新表table,插入__name = mk.ud.log, 为注册表添加 [mk.ud.log] = table 返回1if (luaL_newmetatable(L, "mk.ud.log")) {luaL_Reg m[] = {{"echo", lecho},{"again", lagain},{NULL, NULL},};luaL_newlib(L, m);lua_setfield(L, -2, "__index"); // LUA_REGISTRYINDEX[__index] = stackTopElem// int lua_setmetatable (lua_State *L, int index);// Pops a table or nil from the stack and sets that value as the new metatable for the value at the given index.// 从栈顶弹出一个table或者nil, 将该值设置为给定索引index的新元表lua_setmetatable(L, -2);}return 1;
}static const luaL_Reg l[] = {{"new", lnew},{NULL, NULL},
};int
luaopen_ud_c(lua_State *L) {luaL_newlib(L, l);return 1;
}

编译 lua-ud.c 文件为动态库:

gcc  lua-ud.c -fPIC -shared -o  ud.so -Wall

就会在当前目录会生成 ud.so 文件,执行 lua test-ud.lua

运行结果:

2.3 upvalue上值实战应用

Lua源文件 test-uv.lua

package.cpath = "./?.so"local so = require "uv.c"so.echo("hello world1")
so.echo("hello world2")
so.echo("hello world3")

C源文件 lua-uv.c

#include <lua.h>#include <lauxlib.h>#include <lualib.h>#include <stdio.h>// 闭包实现:  函数 + 上值  luaL_setfuncs
/*int lua_upvalueindex (int i);函数返回一个伪索引,这个伪索引是 i位置表示的上值   i 的范围 [1, 256]Returns the pseudo-index that represents the i-th upvalue of the running function (see §4.2). i must be in the range [1,256].
*/
// lua_upvalueindex(1)
// lua_upvalueindex(2)static int
lecho (lua_State *L) {lua_Integer n = lua_tointeger(L, lua_upvalueindex(1));n++;const char* str = lua_tostring(L, -1);fprintf(stdout, "[n=%lld]---%s\n", n, str);lua_pushinteger(L, n);lua_replace(L, lua_upvalueindex(1));return 0;
}static const luaL_Reg l[] = {{"echo", lecho},{NULL, NULL},   // 必须以{NULL, NULL},结尾
};int
luaopen_uv_c(lua_State *L) { // local tbl = require "tbl.c"luaL_newlibtable(L, l);// 1lua_pushinteger(L, 0);// 2/*void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup);将l数组中所有的function 注册到栈顶的table中当 nup 不为零时,所有函数都使用 nup up值创建,并使用先前推送到库表顶部堆栈上的 nup 值的副本进行初始化*/luaL_setfuncs(L, l, 1);// 上值// luaL_newlib(L, l);return 1;
}

编译 lua-uv.c 文件为动态库:

gcc  lua-uv.c -fPIC -shared -o  uv.so -Wall

就会在当前目录会生成 uv.so 文件,执行 lua test-uv.lua
运行结果:

推荐一个零声学院免费教程,个人觉得老师讲得不错,
分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
TCP/IP,协程,DPDK等技术内容,点击立即学习:

Lua C接口编程(二)相关推荐

  1. 通达信接口进行二次编程开发步骤

    大家都知道通达信接口是比较流行的快速通达信数据excel接口,能够提供多家券商,包括通达信数据excel接口.量化回测平台等. 通达信接口API接口说明(部分) 今天小编主要讲一下,关于通达信接口进行 ...

  2. JAVA编程思想(二)如何面向接口编程

    1. 接口的本质 接口封装了细节 接口对调用者封装了实现细节,调用者只需按接口规范使用,而不关心怎么实现,例如我们最常见的数据库连接接口Connection,当通过某个工具包获取Connection后 ...

  3. 初识Django —Python API接口编程入门

    初识Django -Python API接口编程入门 一.WEB架构的简单介绍 Django是什么? Django是一个开放源代码的Web应用框架,由Python写成.我们的目标是用Python语言, ...

  4. 为什么有人说面向对象编程就是面向接口编程?

    "面向对象编程就是面向接口编程" 这句话相信, 很多人都在网上见过, 装b利器. 我一开始也是这么想的, 那些装b者丢下这一句, 就没下文了. 首先, 我认为这句话是1个假命题. ...

  5. C语言面向对象编程(四):面向接口编程

    Java 中有 interface 关键字,C++ 中有抽象类或纯虚类可以与 interface 比拟,C 语言中也可以实现类似的特性. 在面试 Java 程序员时我经常问的一个问题是:接口和抽象类有 ...

  6. Java中的面向接口编程

    面向接口编程是很多软件架构设计理论都倡导的编程方式,学习Java自然少不了这一部分,下面是我在学习过程中整理出来的关于如何在Java中实现面向接口编程的知识.分享出来,有不对之处还请大家指正. 接口体 ...

  7. 面向接口编程,你考虑过性能吗?

    大家在平时开发中大多都会遵循接口编程,这样就可以方便实现依赖注入也方便实现多态等各种小技巧,但这种是以牺牲性能为代价换取代码的灵活性,万物皆有阴阳,看你的应用场景进行取舍. 一:背景 1. 缘由 在项 ...

  8. Linux 串口编程二 深入了解 termios

    前言 这一系列串口编程重点在应用层编程,但是在讲解原理与相关概念时需要对驱动框架有个基础的认识.如果只是浅尝辄止,以后在遇到串口驱动与应用层程序调试难免遇到瓶颈.关于 tty驱动架构参见我的其他博客: ...

  9. 面向接口编程VS《倚天屠龙记》里张三丰教无忌打太极

    搞笑哈,只细想想,编程和太极怎么能联系在一起了,是八秆子也打不着的哈! 昨天看了一篇文章是关于面向接口编程的文章,颇有心得,其实在今天中国IT软件行业的盛行,程序员们突飞猛涨,真正算的上程序员的又有几 ...

最新文章

  1. 【leetcode】Best Time to Buy and Sell Stock
  2. 熟读《阿里巴巴java开发手册》(六、工程结构,七、 设计规约,专有名词解释)
  3. 新年伊始 .Net7 preview1 发布!
  4. python3小游戏源代码_Python3制作仿“FlappyBird”小游戏|python3教程|python入门|python教程...
  5. (Oracle)关于blob转到目标库报ORA-01461: 仅能绑定要插入 LONG 列的 LONG 值错误解决方案...
  6. Spring Boot Mybatis 搞反向工程,太方便咯。。
  7. 房地产软件信息化——CRM的“中海模式”穆利堂-movno1
  8. Skype国际版最新版及老版本下载
  9. C语言【库函数与自定义函数】详解
  10. 微信小程序实例源码下载
  11. ENGLISH-剑桥-朗文-柯林斯-韦氏dictionary
  12. atv320说明书_施耐德变频器参数设置ATV320学习资料
  13. 谷粒商城高级篇(39)——认证服务之验证码注册
  14. java 解析unicode,解析Unicode编码和Java char
  15. 创新电影院意在传播中华民族优秀传统文化
  16. PS4 自建HEN服务器 | 使用IDM 克隆整个网站
  17. 4.2 期货每日早盘操作建议
  18. RLC电阻电容电感基础知识——电容篇
  19. JAVA 初步学习一
  20. 汉语编程能给我们带来什么?

热门文章

  1. android 百度坐标 gps,Android中gps定位不返回经纬度的解决方案
  2. webpack-yarn包下载
  3. 核心之外的8个必备Maven插件
  4. Dialog(对话框窗口)
  5. 等级保护安全要求:二、三、四级内容及对比
  6. html +css +js+jq学习
  7. NRF52840学习历程(四)定时器
  8. 【听】百年孤独,拉丁美洲悲剧奋斗史
  9. Win 10 环境下 eclipse 安装使用教程
  10. Trafodion ROLLUP函数