LUA调用C(一)-----CAPI

LUA调用C(一)-----CAPI

一:为什么要使用Lua调用C函数

在lua中调用C函数可以提高程序的运行效率。所以lua与C的相互调用在工程中相当实用,本文就来讲解lua与C相互调用的方法。

二:Lua调C函数实现原理

​ Lua与C相互调用的首要问题是如何交换数据,lua API使用了一个抽象的栈与C语言交换数据,提供了压入元素,查询元素和弹出元素等功能的API操作栈,这里可以查看lua5.2中每个函数的详细文档,栈中的元素可以通过索引访问,从栈底向上是从1开始递增的正整数,从栈顶向下是从-1开始递减的负整数,栈的元素按照FIFO的规则进出。

三:Lua调C

​ lua可以将C函数注册到lua中,C函数必须遵循统一的原型,这个原型定义在lua.h中。

	typedef int (*lua_CFunction)(lua_State* L)

​ 这个函数包含的参数是 lua_State 类型的指针 L 。可以通过这个指针进一步获取通过 Lua 代码传入的参数。这个函数的返回值类型是一个整型,表示返回值的数量。需要注意的是,用 C 编写的函数无法把返回值返回给 Lua 代码,而是通过虚拟栈来传递 Lua 和 C 之间的调用参数和返回值。

​ 用C函数扩展lua时,一般将所有的C函数编译成一个独立的模块,方便增加新的函数。

​ Demo:

#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
#include <stdio.h>

//实现函数
static int show_lua(lua_State *L){
    const char *str = lua_tostring(L, 1);//获取参数、字符串
    //const cahr *lua_tostring(lua_State *L,int index)
    //lua_Number(double) lua_tonumber(lua_State *L, int index);//number
    
    int ret = show(str);		//调用函数
    lua_pushnumber(L, ret);		//压入结果
    return 1;//返回结果数量
}

//申明一个数组,包含模块中所有的函数及名称。数组元素的类型为luaL_Reg结构
static const struct luaL_Reg mylib[] = {
    {"show_lua" , show_lua},
    {NULL, NULL}//固定结尾
};

//声明一个主函数,用于创建C模块。函数返回时,会将table留在栈中。
int luaopen_mylib(lua_State *L){
    luaL_newlib(L, mylib); 		//5.2 ,创建(复用)一个table,并用数组ding_lib中的信息填充这个table
    //luaL_register(L, "lib",lib); 		// lua 5.1
    return 1;		//返回1,表示将这个table返回给Lua
}

//测试的功能函数
int show(char *str)
{
	int ret = 0;
	if(str == NULL){
		ret = -1;
	}
	else{
		printf("输入:%s\n",str);
	}

	return ret;
}

​ 每个被lua调用的C函数都有自己的私有栈,压入参数的索引从1开始递增,结果值也是直接压入栈中,函数返回时会将压入的参数全部删除,只留下结果值。

​ mylib[]声明了模块中所有C函数列表,每一项映射了C函数在lua中的命名,比如上面代码中show函数在lua中用show_lua表示,列表必须用{NULL, NULL}结束。

​ luaL_newlib在栈中创建一个table,将mylib数组中的C函数注册进这个table中。 luaopen_mylib将这个table中的函数加载进lua环境中。

四、编译生成动态库,供Lua调用

gcc -shared -fPIC demo.c -lluajit-5.1 -L /usr/local/openresty/luajit/lib -I /usr/local/openresty/luajit/include/luajit-2.1 -o mylib.so

lua代码中,require会查找 mylib.so,并调用该链接库中的 luaopen_mylib,luaopen_的后缀必须与动态链接库名字一样,这是由require查找函数方式决定的。

为了方便我们测试,我们在 LD_LIBRARY_PATH这个环境变量中加入了刚刚库所在的路径

export LD_LIBRARY_PATH=$PWD	

五、Lua调用

​ demo.lua:

local f = require “mylib”

local str = "Hello World"

print(f.show_lua(str))

调用C模块:

lua demo.lua
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值