博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
(原)lua使用ffi调用c程序的函数
阅读量:4551 次
发布时间:2019-06-08

本文共 3127 字,大约阅读时间需要 10 分钟。

转载请注明出处:

参考网址:

1. 新建calcmath.cpp,输入:

1 #include 
2 #include
3 #include
4 //using namespace std; 5 6 7 extern "C" { 8 float isquare(float val); 9 double isqrt(double val);10 void ivecadd(double* a, double* b, int len);11 }12 13 float isquare(float val)14 {15 return val*val;16 }17 18 double isqrt(double val)19 {20 return sqrt(val);21 }22 23 void ivecadd(double* a, double* b, int len)24 {25 for (int i = 0; i < len; ++i)26 {27 a[i] = a[i] + b[i];28 }29 }

说明:包含三个函数:isquare计算平方,isqrt计算开方,ivecadd计算两个数组对应元素之和。

2. 在终端中输入:

g++ -shared -fPIC -o libcalcmath.so calcmath.cpp

此时当前文件夹内会生成libcalcmath.so。

说明:不能使用gcc,会提示如下错误:

undefined symbol: _ZNSt8ios_base4InitD1Ev

截图如下:

3. 新建调用该库的lua文件:calcmath.lua(名字随便),并输入:

1 calcmath = {} 2  3 local ffi = require("ffi") 4  5 ffi.cdef[[ 6 float isquare(float val); 7 double isqrt(double val); 8 void ivecadd(double* a, double* b, int len); 9 ]]10 11 calcmath.C = ffi.load('calcmath')12 13 --[[local squareVal = calcmath.C.isquare(5)    -- call functions in this file14 print(squareVal)15 local sqrtVal = calcmath.C.isqrt(5)16 print(sqrtVal)17 18 local a = ffi.new('double[2]', {5.2, 6.7})19 local b = ffi.new("double[2]", {3, 7})20 21 local x = ffi.cast('double&',a)22 local y = ffi.cast('double&',a+1)23 24 calcmath.C.ivecadd(a, b, ffi.sizeof(a)/8)25 print(tonumber(x), tonumber(y))26 print(ffi.sizeof(a))27 ]]

说明:a上面注释的代码实际可以直接使用,此时在当前文件内直接调用c函数。如果只在当前文件使用calcmath,可以加上local,如local calcmath = {}。如果要在其他文件内使用calcmath,则不能加上local,否则会提示:

b 该文件名字如果为ffi.lua的话,可能不能在其他文件内成功调用(应该是与系统文件ffi.lua冲突):

也可能能调用成功(在另一台电脑上试了一下,如果用include则失败,如果用dofile则成功。。。)。

160830更新:刚才又试了一下,即便该文件名字为‘ffi.lua’,无论是include还是dofile,都能成功:test.lua的前6行如下:

local ffi = require("ffi")--include 'ffi.lua'       -- this line and the following 2 line are both okrequire 'paths'paths.dofile('ffi.lua')

如果不加第一句require就不行。估计程序能区分开哪个是系统的库文件,哪个是当前的文件。。。先将就着这样理解吧。

c libcalcmath.so文件可以放在当前文件夹下,也可以放在/usr/lib下;不论放在当前文件夹还是/usr/lib下,代码中均不用加上lib及.so,ffi.load 时会自动添加。当然在代码中也可以加上,如libcalcmath或libcalcmath.so或calcmath.so。我这边试了,如果放在其他文件夹下,需要使用绝对路径,并且需要使用库的完整名libcalcmath.so,如:/home/XXX/libcalcmath.so,否则会提示:

4. 新建测试程序test.lua,并输入:

1 local ffi = require("ffi") 2  3 --include 'calcmath.lua'       -- this line and the following 2 line are both ok 4  5 require 'paths' 6 paths.dofile('calcmath.lua') 7  8 local C = calcmath.C 9 10 local squareVal = C.isquare(5)11 print(squareVal)12 local sqrtVal = C.isqrt(5)13 print(sqrtVal)14 15 local a = ffi.new('double[2]', {
5.2, 6.7})16 local b = ffi.new("double[2]", {
3, 7})17 18 local x = ffi.cast('double&',a)19 local y = ffi.cast('double&',a+1)20 21 C.ivecadd(a, b, ffi.sizeof(a)/8)22 print(tonumber(x), tonumber(y))23 print(ffi.sizeof(a))

说明:a第一句local ffi = require("ffi")必须要,否则下面的ffi.new无法使用。

b 不确定是否需要释放new出来的内存。。。(以后碰到了再说吧)。

5. 结果:

使用th test.lua结果如下:

无法使用lua test.lua,会提示如下的错误:

使用luajit test.lua,结果如下:

说明

如果isqrt中参数类型使用float的话,精度会有损失,结果为:

2.2360680103302

使用double后,结果为:

2.2360679774998

使用计算器的结果:

2.2360679774997896964091736687313

可见,使用double后,精度范围内结果一致。

转载于:https://www.cnblogs.com/darkknightzh/p/5812763.html

你可能感兴趣的文章
记录下zend studio 的xdebug 在调试安装
查看>>
ES6阅读笔记
查看>>
数字基带信号分类
查看>>
移动HTML5前端性能优化指南(转)
查看>>
Jq 遍历each()方法
查看>>
Android源码分析:Telephony部分–phone进程
查看>>
关于 redis.properties配置文件及rule
查看>>
WebService
查看>>
关于Java中重载的若干问题
查看>>
Java中start和run方法的区别
查看>>
23种设计模式中的命令模式
查看>>
[转载]年薪10w和年薪100w的人,差在哪里?
查看>>
shell 日期参数
查看>>
package的使用
查看>>
括号生成
查看>>
优秀的前端需要做到什么?
查看>>
aws cli command line interface的安装与使用
查看>>
10)将地址换成常量
查看>>
箭头函数
查看>>
android MVC &amp;&amp; MVP &amp;&amp; MVVM分析和对照
查看>>