(原)lua使用ffi调用c程序的函数

转载请注明出处:

http://www.cnblogs.com/darkknightzh/p/5812763.html

参考网址:

http://luajit.freelists.narkive.com/Yhm9jicx/unexpected-type-conversion-for-arithmetic-with-cdata-double

http://luajit.org/ext_ffi_semantics.html#convert_fromlua

https://github.com/szagoruyko/loadcaffe

1. 新建calcmath.cpp,输入:

 1 #include <iostream>
 2 #include <cmath>
 3 #include <stdio.h>
 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 file
14 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则成功。。。)。

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后,精度范围内结果一致。

时间: 2024-08-26 12:52:08

(原)lua使用ffi调用c程序的函数的相关文章

C程序与Lua脚本相互调用

Lua脚本是一种可用于C程序开发/测试的工具,本篇介绍一下C程序与Lua脚本如何进行相互调用,更加详细的操作参见<Programing in Lua>.本文分为3个部分:1.Windows环境下Lua的下载以及安装注意事项:2.Visual C++6.0中Lua的配置:3.C程序与Lua脚本相互调用实例. 1.Windows环境下Lua的下载以及安装注意事项 a.下载Lua for Windows,笔者用的版本是V5.1.4-35: b.上微软官网,下载Visual C++运行库——vcred

asp.net网页调用客户端程序

================================第一步:网注册表中(HKEY_CLASSES_ROOT)添加项 ================================第二步:在网页上写上标签调用 <a href="xishui://hello">zhangdi://hello</a> ================================显示效果:会弹出hello asp.net网页调用客户端程序,布布扣,bubuko.com

c# 调用外包程序 等待处理完成结果

string root = @"J:\yaoqianshu"; string pythonPath = "解压缩拷贝启动动画测试(新).py"; string ccccPath = ""; ProcessStartInfo myProcess = new ProcessStartInfo(); myProcess.WorkingDirectory = root; myProcess.FileName = pythonPath; Process o

Windows、Linux、Web安装及调用Matlab程序完整说明(大章)

本文档详细说明了Linux下Web项目调用Matlab函数的完整操作,文章适合对Java.Linux有一定基础了解的人群(不了解也没什么,无非是多试几次).因Linux作为服务器,所以未在其上安装Matlab主程序,只安装了运行环境MCR. 本文档内所述的所有版本软件均以32位为准,JDK与MCR也使用32位.若你的系统为64位,Linux系统同样为64位,则请尽量选择使用64位版本的JDK与MCR. 由于Matlab的版本限制问题,请保证Matlab主程序和MATLABCompiler Run

C 可变长参数运用-----编写Lua的通用调用函数

1.C可变长参数 printf这个使用频繁的C语言函数的参数列表包含一个const char*的描述串,还有一个可变长参数(...) ,如下为printf的函数声明. int printf(const char * __restrict, ...) 在stdarg.h这个头文件中包含着对可变长参数进行操作的一些宏(x86平台为例): #define va_start(ap,v)( ap = (va_list)&v + _INTSIZEOF(v) ) #define va_arg(ap,t) ( 

在C#中调用控制台程序

需求:  想在C#中调用一个带有参数 dos命令  whoami,并处理返回的文本信息 调查:  一查看 发现是个 .exe 的问件, 并且这个.exe可以根据不同的参数,得到不同的系统信息 解决方案:问度娘要了一点资料,度娘很爽快地答应了我,解决需求 参考的网页我放到了文章的末尾 关键代码: 新建了个窗体程序,代码在载入窗体的时候执行,只是个小demo,就不多说了 private void Form1_Load(object sender, EventArgs e)         { //实

【Qt】使用QProcess调用其它程序或脚本

大概试了一下,还是不错的,不过字符编码问题还不太好解决: 代码: #include "mainwindow.h" #include "ui_mainwindow.h" #include <QMessageBox> #include <QProcess> #include <QTextCodec> #include <QCloseEvent> MainWindow::MainWindow(QWidget *parent)

WEB程序调用客户端程序

最近一个项目中要点击WEB页面上的链接启动自己编写的程序,而且还要接收参数,google了1.5小时,终于初步试验通过了. 尝试google了:web send message windows form, bs call cs program, custom protocol...多个关键字组合,发现这种技术叫 registered URL protocol,在这篇文章里介绍得比较详细: http://msdn.microsoft.com/en-us/library/aa767914(v=vs.

[转]自定义URL Protocol Handler,从网页调用EXE程序

转自:http://www.cnblogs.com/zjneter/archive/2008/01/08/1030066.html 迅雷,电驴等软件可以在浏览器中点击一个url后自动启动,并执行操作.这是咋实现的呢? 要实现这个功能笼共分3步.(我们注册一个xishui:// 这样的 protocol-handler,实现在网页中点击xishui://hello,就弹出一个对话框,上面显示"hello")1 按照如下结构建立注册表  其中 [xishui] 是建立在注册表的 [HKEY