• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

从lua调用C函数

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

最近在进入Lua编程的状态,一度令我困惑的是,Lua提供的功能少的可怜,跟自备电池的python相比,可说是简陋了。连table的打印,都需要自己实现,也因此有了一打的第三方方案。后来我想明白了,以Lua和C如此紧密的关系,只需要建立Lua的binding,那么丰富而性能强大的C库资源完全可以为Lua所用,这样就不愁功能缺失了。

 

关于C调用Lua,前段时间已经写过一篇短文了:《多语言协作与二进制交互》,现在补上从Lua调用C的这一篇。先上一段Lua代码:

#!/usr/bin/lua
require("power")
print(square(1.414213598))
print(cube(5))

在这段代码里,我引用了一个power模块,并且调用了power模块里的square函数和cube函数。由此可知,在C语言编写的power模块里面,需要有相关的函数可以注册本模块提供的函数,并且让Lua可以“感知”到自身是一个模块。回忆一下Lua的路径搜索,可以看到除了后缀名为*.lua的文件之外,还有*.so文件,所以C扩展是编译为.so的。实际情况是,在执行require语句的时候,系统会调用luaopen_power函数,这个函数名是通过luaopen_与power这个模块名拼接得到的。

 

现在看看luaopen_power函数的定义:

int luaopen_power(lua_State *L){
    lua_register(
            L,               /* Lua 状态机 */
            "square",        /*Lua中的函数名 */
            isquare          /*当前文件中的函数名 */
            );  
    lua_register(L,"cube",icube);
    return 0;
}

可以看到,通过调用lua_register函数,我们在L这个lua虚拟机里面注册了两个函数,一个是square,一个是cube,他们分别对应到isquare和icube这两个C函数。

 

回过头来看一看,lua脚本里,这条简单的require语句,执行了两个步骤:一是先把名字为power.so的文件加载起来,二是调用其中的luaopen_power函数。下面来看一下具体的函数如何定义:

static int isquare(lua_State *L){              /* C中的函数名 */
    float rtrn = lua_tonumber(L, -1);      /* 从Lua虚拟机里取出一个变量,这个变量是number类型的 */
    printf("Top of square(), nbr=%f\n",rtrn);
    lua_pushnumber(L,rtrn*rtrn);           /* 将返回值压回Lua虚拟机的栈中 */
    return 1;                              /* 这个返回值告诉lua虚拟机,我们往栈里放入了多少个返回值 */
}

注释的讲解比较详细了,可以看到为Lua定义的C函数格式都是比较统一的,首先接受一个Lua虚拟机变量L,然后从L里取出相应的参数(需要指定数据类型),最后将返回值再次压回虚拟机里面,通过返回int告诉Lua虚拟机,自己的返回值有多少个。

 

好,到这里就只差最后一步了,现在把这段C代码编译成.so文件。使用如下的编译参数:

ubuntu@ubuntu:~$ gcc -Wall -shared -fPIC -o power.so  -I/usr/include/lua5.1 -llua5.1   hellofunc.c

(hellofunc.c记得要include lua.h, lauxlib.h, lualib.h三个头文件哦)

这里解释一下两个参数的意思,-shared是告诉gcc,需要编译成.so文件,并且这个源文件里面不会有main函数,不要大惊小怪。另一个-fPIC,是Position Independent Code的意思,具体的含义可以参考这篇,主要用来避免同一份代码因为重定位位置不同而在内存中存在多个实例。

调用的结果:

ubuntu@ubuntu:~$ ./hellofunc.lua
Top of square(), nbr=1.414214
2.0000002687177
Top of cube(), number=5.000000
125

当然,如果机器安装有多个版本的Lua,需要指定执行hellofunc.lua的lua解释器版本。因为本篇教程是针对Lua5.1的,所以需要指定Lua5.1来执行,例如lua5.1 hellofunc.lua,否则用lua5.2调用会引起core dump


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
【Lua】使用随机数(转)发布时间:2022-07-22
下一篇:
lua-excel助手发布时间:2022-07-22
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap