转载请注明出处:

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. extern "C" {
  7. float isquare(float val);
  8. double isqrt(double val);
  9. void ivecadd(double* a, double* b, int len);
  10. }
  11.  
  12. float isquare(float val)
  13. {
  14. return val*val;
  15. }
  16.  
  17. double isqrt(double val)
  18. {
  19. return sqrt(val);
  20. }
  21.  
  22. void ivecadd(double* a, double* b, int len)
  23. {
  24. for (int i = ; i < len; ++i)
  25. {
  26. a[i] = a[i] + b[i];
  27. }
  28. }

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

2. 在终端中输入:

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

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

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

  1. 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则成功。。。)。

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

  1. local ffi = require("ffi")
  2.  
  3. --include 'ffi.lua' -- this line and the following 2 line are both ok
  4.  
  5. require 'paths'
  6. 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()
  11. print(squareVal)
  12. local sqrtVal = C.isqrt()
  13. print(sqrtVal)
  14.  
  15. local a = ffi.new('double[2]', {5.2, 6.7})
  16. local b = ffi.new("double[2]", {, })
  17.  
  18. local x = ffi.cast('double&',a)
  19. local y = ffi.cast('double&',a+)
  20.  
  21. C.ivecadd(a, b, ffi.sizeof(a)/)
  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后,精度范围内结果一致。

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

  1. lua使用ffi调用c程序的函数

    参考: https://blog.csdn.net/weiwangchao_/article/details/16880401   http://luajit.org/ext_c_api.html h ...

  2. C程序与Lua脚本相互调用

    Lua脚本是一种可用于C程序开发/测试的工具,本篇介绍一下C程序与Lua脚本如何进行相互调用,更加详细的操作参见<Programing in Lua>.本文分为3个部分:1.Windows ...

  3. Python基础笔记系列十四:python无缝调用c程序

    本系列教程供个人学习笔记使用,如果您要浏览可能需要其它编程语言基础(如C语言),why?因为我写得烂啊,只有我自己看得懂!! python语言可以对c程序代码进行调用,以弥补python语言低性能的缺 ...

  4. lua 15 协程-协同程序

    转自:http://www.runoob.com/lua/lua-coroutine.html 什么是协同(coroutine)? Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈 ...

  5. MATLAB调用C程序、调试和LDPC译码

    MATLAB是一个很好用的工具.利用MATLAB脚本进行科学计算也特别方便快捷.但是代码存在较多循环时,MATLAB运行速度极慢.如果不想放弃MATLAB中大量方便使用的库,又希望代码能迅速快捷的运行 ...

  6. 在ORACLE触发器里调用JAVA程序

    因为项目需要,有一个已经写好的Java程序,想要在Oracle某个表的触发器中调用,以使得每次数据更新时,调用这个JAVA程序,来修改后台某个数据. 现将过程记录如下: 1.编写JAVA程序 publ ...

  7. Oracle触发器反向调用Java程序

    导入jar包 在oracle中导入需要的jar包,我们把编辑好的java类打成jar包,直接在oarcle里面写简单的调用就可以了, 1.操作系统需要拥有支持loadjava命令的jdk. 2.加载j ...

  8. C/C++程序通过动态链接库调用MATLAB程序

    C/C++程序通过动态链接库调用MATLAB程序 1 MATLAB编译器设置 需要设定对应的C++编译器才能编译.m文件生成可供C++调用的库文件. 在MATLAB命令行输入:mex –setup:然 ...

  9. tengine lua 开源一 调用内部接口高效发送文件

    tengine  lua 开源一 调用内部接口高效发送文件 开源自己封装的sendfile 模块,可以高效的通过lua发送文件 源码地址:https://github.com/weinyzhou/Lu ...

随机推荐

  1. 【原创】C++中对象的序列化

    1.对象序列化 对象的序列化是指将对象的状态信息转换为可以存储或者传输的形式的过程.对象的反序列化是与序列化相反的过程. 在序列化期间,对象将其当前的状态写入到临时或者永久性的存储区,可以通过从存储区 ...

  2. Java 中字符串的子串搜索

    基友前两天参加了阿里的实习生面试,问了个问题,就是关于字符串的子串搜索的问题.想想实现方式无非就是两层循环,但是 java 中是有现成实现的,于是我就去查查源码,看看 java 语言怎么实现这个的,发 ...

  3. JS判断访问设备、客户端操作系统类型

    先给出一个实例:判断windows.linux.android 复制以下代码另存为html文件即可. <html> <head> <title>判断操作系统< ...

  4. NAS4Free 安装配置(三)基本配置

    基本配置 在浏览器中输入地址,进入管理界面(我的是http://192.168.0.10) 登录界面 初始用户名:admin,初始密码:nas4free 首页 进入基本配置 这里可以选择语言,有中文, ...

  5. python文件_批量改名

    #! /usr/bin/env python #coding=gbk #文件操作实例--将文件夹下所有图片名称加上'_test' import re,os,time #str.split(path) ...

  6. JS 多种变量定义

    对象直接量创建一个对象:  var obj = {x:[1,2],y:23}; 代码跟下面是一样的.  var obj=new Object(); obj.x=new Array(1,2); obj. ...

  7. js给div动态添加控件,然后给这个控件动态添加事件

    <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx. ...

  8. c#添加事物(全部执行和带保存点的执行)

    全部执行 protected void Button2_Click(object sender, EventArgs e) { // 执行事务 SqlConnection con = new SqlC ...

  9. CloudStack核心类ApiServlet、ApiServer、ApiDispatcher、GenericDaoBase源码分析

    ApiServlet 首先从整体上看下ApiServlet,Outline视图如下, 一.注意@Inject依赖的是javax.inject.jar,它和spring的@Autowired的区别在于使 ...

  10. 自定义JsonResult处理JSON序列化DateTime类型数据(Ext4.2+ASP.NET MVC 4)

    最近项目中前台页面使用Extjs4.2 ,在后台ASP.NET MVC4返回的DateTime类型的数据错返回的DateTime类型的JsonResult的结果中的值是“\/Date(13784461 ...