luajit日记-FFI库

2019独角兽企业重金招聘Python工程师标准>>> hot3.png

LuaJIT FFI LibraryThe FFI library allows calling external C functions and using C data structures from pure Lua code. 
The FFI library largely obviates the need to write tedious manual Lua/C bindings in C. No need to learn a separate binding language — it parses plain C declarations! These can be cut-n-pasted from C header files or reference manuals. It's up to the task of binding large libraries without the need for dealing with fragile binding generators. 
The FFI library is tightly integrated into LuaJIT (it's not available as a separate module). The code generated by the JIT-compiler for accesses to C data structures from Lua code is on par with the code a C compiler would generate. Calls to C functions can be inlined in JIT-compiled code, unlike calls to functions bound via the classic Lua/C API.
This page gives a short introduction to the usage of the FFI library. Please use the FFI sub-topics in the navigation bar to learn more. Motivating Example: Calling External C Functions
It's really easy to call an external C library function:local ffi = require("ffi")ffi.cdef[[int printf(const char *fmt, ...);]]ffi.C.printf("Hello %s!", "world")
So, let's pick that apart:
1.Load the FFI library.
2.Add a C declaration for the function. The part inside the double-brackets (in green) is just standard C syntax.
3.Call the named C function — Yes, it's that simple! Actually, what goes on behind the scenes is far from simple: ③ makes use of the standard C library namespace ffi.C. Indexing this namespace with a symbol name ("printf") automatically binds it to the standard C library. The result is a special kind of object which, when called, runs the printf function. The arguments passed to this function are automatically converted from Lua objects to the corresponding C types.
Ok, so maybe the use of printf() wasn't such a spectacular example. You could have done that with io.write() and string.format(), too. But you get the idea ...
So here's something to pop up a message box on Windows:local ffi = require("ffi")ffi.cdef[[int MessageBoxA(void *w, const char *txt, const char *cap, int type);]]ffi.C.MessageBoxA(nil, "Hello world!", "Test", 0)
Bing! Again, that was far too easy, no?
Compare this with the effort required to bind that function using the classic Lua/C API: create an extra C file, add a C function that retrieves and checks the argument types passed from Lua and calls the actual C function, add a list of module functions and their names, add a luaopen_* function and register all module functions, compile and link it into a shared library (DLL), move it to the proper path, add Lua code that loads the module aaaand ... finally call the binding function. Phew!Motivating Example: Using C Data Structures
The FFI library allows you to create and access C data structures. Of course the main use for this is for interfacing with C functions. But they can be used stand-alone, too.
Lua is built upon high-level data types. They are flexible, extensible and dynamic. That's why we all love Lua so much. Alas, this can be inefficient for certain tasks, where you'd really want a low-level data type. E.g. a large array of a fixed structure needs to be implemented with a big table holding lots of tiny tables. This imposes both a substantial memory overhead as well as a performance overhead.
Here's a sketch of a library that operates on color images plus a simple benchmark. First, the plain Lua version:local floor = math.floorlocal function image_ramp_green(n)local img = {}local f = 255/(n-1)for i=1,n doimg[i] = { red = 0, green = floor((i-1)*f), blue = 0, alpha = 255 }endreturn imgendlocal function image_to_grey(img, n)for i=1,n dolocal y = floor(0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blue)img[i].red = y; img[i].green = y; img[i].blue = yendendlocal N = 400*400local img = image_ramp_green(N)for i=1,1000 doimage_to_grey(img, N)end
This creates a table with 160.000 pixels, each of which is a table holding four number values in the range of 0-255. First an image with a green ramp is created (1D for simplicity), then the image is converted to greyscale 1000 times. Yes, that's silly, but I was in need of a simple example ...
And here's the FFI version. The modified parts have been marked in bold:local ffi = require("ffi")ffi.cdef[[typedef struct { uint8_t red, green, blue, alpha; } rgba_pixel;]]local function image_ramp_green(n)local img = ffi.new("rgba_pixel[?]", n)local f = 255/(n-1)for i=0,n-1 doimg[i].green = i*fimg[i].alpha = 255endreturn imgendlocal function image_to_grey(img, n)for i=0,n-1 dolocal y = 0.3*img[i].red + 0.59*img[i].green + 0.11*img[i].blueimg[i].red = y; img[i].green = y; img[i].blue = yendendlocal N = 400*400local img = image_ramp_green(N)for i=1,1000 doimage_to_grey(img, N)end
Ok, so that wasn't too difficult:
1.First, load the FFI library and declare the low-level data type. Here we choose a struct which holds four byte fields, one for each component of a 4x8 bit RGBA pixel.
2.Creating the data structure with ffi.new() is straightforward — the '?' is a placeholder for the number of elements of a variable-length array.
3.C arrays are zero-based, so the indexes have to run from 0 to n-1. One might want to allocate one more element instead to simplify converting legacy code.
4.Since ffi.new() zero-fills the array by default, we only need to set the green and the alpha fields.
5.The calls to math.floor() can be omitted here, because floating-point numbers are already truncated towards zero when converting them to an integer. This happens implicitly when the number is stored in the fields of each pixel.
Now let's have a look at the impact of the changes: first, memory consumption for the image is down from 22 Megabytes to 640 Kilobytes (400*400*4 bytes). That's a factor of 35x less! So, yes, tables do have a noticeable overhead. BTW: The original program would consume 40 Megabytes in plain Lua (on x64).
Next, performance: the pure Lua version runs in 9.57 seconds (52.9 seconds with the Lua interpreter) and the FFI version runs in 0.48 seconds on my machine (YMMV). That's a factor of 20x faster (110x faster than the Lua interpreter).


转载于:https://my.oschina.net/u/1449160/blog/199760

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/291916.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux c之access方法介绍

1、函数介绍 access函数检查调用进程是否可以对指定的文件执行某种操作 api: int access(const char * pathname, int mode) athname:需要检测的文件路劲名 mode:需要测试的操作模式 mode参数介绍: R_OK 测试读许可权 W_OK 测试写许可权 X_OK 测试执行许可…

P4 前端编译器p4c-bm、后端编译器bmv2命令安装 make error问题

参考:Github 安装p4c-bm: sudo pip install -r requirements.txtsudo pip install -r requirements_v1_1.txt //if you are interested in compiling P4 v1.1 programssudo python setup.py install 测试: p4c-bmv2 -h 弹出相关信息&#xff…

机器学习模型 知乎_机器学习-模型选择与评价

交叉验证首先选择模型最简单的方法就是,利用每一种机器学习算法(逻辑回归、SVM、线性回归等)计算训练集的损失值,然后选择其中损失值最小的模型,但是这样是不合理的,因为当训练集不够、特征过多时容易过拟合,那么训练集…

三种查看SqlServer中数据物理pge页的方法

1.根据数据记录查看当前记录所在的文件编号、page页、以及在页中的插槽。 示例如下: SELECT top 10 %%physloc%%, sys.fn_physlocFormatter (%%physloc%%) AS RID FROM tableName --注意;在64位系统中sys.fn_physlocFormatter 整理出来的格式有时候不…

C#10 和 .NET6 代码跨平台开发

零、前言有数千页长的编程书籍,旨在成为 C# 语言、.NET 库、网站、服务、桌面和移动应用等应用模型的综合参考。这本书不一样。它简洁明了,旨在成为一本轻快有趣的书,每一个主题都有实用的实践演练。总体叙述的广度是以某种深度为代价的&…

文件权限

用户类型:管理员:0一般用户:1-65535系统用户1-499普通用户:500权限管理:owner,group属主:属组:其他:权限:read(读),write&…

linux之tar命令使用总结

1、使用原因 刚才在linux平台需要安装Clion的时候,下载得到CLion-2016.3.2.tar.gz 这个gz的压缩文件,所以需要解压到当前文件夹 2、简单解压到当前文件 解压当前文件夹命令 tar -zxvf CLion-2016.3.2.tar.gz 效果如下 3、tar命令介绍 -c: 建立压缩档案 -x:解压 -t:…

jq取第一个子元素为select_【转】jquery如何获取第一个或最后一个子元素?

【转自】https://www.cnblogs.com/MUMO/p/5938483.html通过children方法,children("input:first-child")$(this).children("input:first-child").val();$(this).children("input:last-child").val();通过>选择器,$(&qu…

基于ASP.NET Core SignalR的流式传输

基于ASP.NET Core SignalR的流式传输SignalR概述SignalR是ASP.NET Core下非常流行的实现Web实时功能的库。微软再文档中列出了适合的应用场景:适合 SignalR 的候选项:需要从服务器进行高频率更新的应用。示例包括游戏、社交网络、投票、拍卖、地图和 GPS…

Leetcode: Palindrome Partition I II

题目一, 题目二 思路 1. 第一遍做时就参考别人的, 现在又忘记了 做的时候使用的是二维动态规划, 超时加超内存 2. 只当 string 左部分是回文的时候才有可能减少 cut 3. 一维动规. 令 cuts[i] 表示string[i, string.size()] 所需的切割数, 那么 状态转移方程为 cuts[i] min(cut…

FatMouse

时间限制:1 秒 内存限制:128 兆 特殊判题:否 提交:1431 解决:641 题目描述:FatMouse prepared M pounds of cat food, ready to trade with the cats guarding the warehouse containing his favorite food…

linux之安装Clion和运行使用总结

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到教程 1、Clion的简单介绍 CLion是以IntelliJ为基础,专为开发C及C++所设计的跨平台IDE,可以在Windows、Linux及MacOS使用,这里我是在ubuntu 16.0.4基础上安装。 2、linux平台…

Tips

1.Unity\Editor\Data\Resources\ScriptTemplates 里的文件是Unity 生成文件的模板. 2.提示文件尾不一致.用VS打开Unity\Editor\Data\Resources\ScriptTemplates里的模板文件.文件->高级保存选项->Windows(CRLF) 3.Scene视图里选择Transform工具,按V可以通过Pivot对齐 4.N…

体验 正式发布 的OSM v1.0.0 版本

2021年10月份发布了OSM 1.0 RC[1],在过去的几个月里,OSM 的贡献者一直在努力为 v1.0.0 版本的发布做准备。2022年2月1日,OSM 团队正式发布 1.0.0 版本[2]。OSM 从最初的发布到现在已经走了很长的路,团队继续专注于社区需要的关键和…

linux c之用命名管道实现进程通信

1、命名管道相关信息介绍 不是很了解命名管道先看这个篇博客 http://blog.csdn.net/u011068702/article/details/55102379 linux c之命名管道简单使用 博客介绍了创建管道的方法,这里还需要介绍 open函数和调用阻塞 FIFO文件也可以使用open调用来打开,mkfifo函数只是创建…

vue表格刷新数据_Vue.js+Layer表格数据绑定与实现更新的实例

一:先使用Vue.js绑定好数据与更新事件使用v-on绑定好事件,在事件里边直接把该行数据传递进去,在更新方法里边就可以直接取出需要更新的数据选择用户名学号班级操作{{item.UserName}}{{item.Number}}{{item.Class}}删除更新//实例化vue.js(用来给表格提供…

数据流图的画法

数据流图的画法 数据流图也称为数据流程图date flow diagram , DFD,是一种便于用户理解和分析系统数据流程的图形工具,他摆脱了系统和详细内容,精确的在逻辑上描写叙述系统的功能、输入、输出和数据存储等,是系统逻辑模型的重要组…

linux之自己总结学习linux的资源推荐

1、学习linux前辈的网站 安卓和linux网络编程 http://www.cnblogs.com/hnrainll/ IBM学习linux技术地址: https://www.ibm.com/developerworks/cn/views/linux/libraryview.jsp 2、学习linux的途径,或者说过程 1、APUE再深读 – 尤其是进程,线程,IPC,套接字 2、 多…

01-算法简介

数据结构和算法 基于《算法图解》—Aditya Bhargava和《数据结构》—严蔚敏 ** 算法图解:(基于Python)* 第1章—算法简介 1.1 引言 算法是一组完成任务的指令。 1.2 二分查找(binary_search) 二分查找是一种算法,其输入是一个…

浏览器渲染机制面试_【前端面试必考题】页面渲染机制(一)

页面渲染机制这部分内容会分成两篇来进行讲解,这两篇里我们准备聊一下页面的渲染的过程,包括页面的加载、DOM 树的构建、CSSOM 树的构建、渲染树的构建和最后的渲染过程等。浏览器的渲染机制和网页的优化息息相关,只有知道了页面是怎么渲染出…