Lua ffi
所有传递到lua的变量都必须在C里定义全局变量:
ffi.cdef[[ --[]数组变量大小可以不填int n[]; --定义一个全局变量,才能传递int num; --数值int str[]; --字符串、数组都是这种]]
关于C头文件:
#include <stdio.h> --使用 printf 函数必须加#include <string.h> --使用 strcpy 函数必须加
 
实例:
Lua传参到C,并修改后返回:
--myffi.c#include <string.h>#include <stdio.h>char str(char* L){printf("string=%s\n",L);printf("string*=%p\n",L);strcpy(L,"abc "); --修改字符串 需要#include <string.h>return 0;}int num(int L){printf("number=%d\n",L);printf("number*=%p\n",L);int b = 2200;return L+b;}
--hello.lualocal ffi=require"ffi"local myffi = ffi.load('myffi')ffi.cdef[[char str(char* L);int num(int L);]]local a="人鱼"local b=1100--传入地址-- local p = ffi.cast('char*', a)-- myffi.str(p)-- print("a="..a)-- local p = ffi.cast('int', b)-- b=myffi.num(p)-- print(b)
linux编译:
gcc -g -o myffi.so -fpic -shared myffi.c
win系统
gcc -m32 -g -o myffi.dll -fpic -shared myffi.c
环境变量(遇到ffi.load报错需要设置):
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:your_lib_path
运行:
./lua-5.1.5/src/lua hello.lua
C++例子
//myffi.cpp#include <iostream>using namespace std;int main(){cout << "Hello, world111111111111!" << endl;return 0;}//hello.lualocal ffi=require"ffi"local myffi = ffi.load('myffi')ffi.cdef[[int main();]]myffi.main()
编译
g++ -m32 -g -o myffi.dll -fpic -shared myffi.cpp
C传参到Lua:
--lualocal ffi=require"ffi"local myffi = ffi.load('myffi')ffi.cdef[[char a[]; --C语言里面全局变量,才可以返回值char* str(); --字符串返回指针int b; --C语言里面全局变量,才可以返回值int num(); --数值直接返回]]a=myffi.str()print(ffi.string(a)) --类型cdata 指针 转换成 Stringb=myffi.num()print(b)
--cchar a[]="abcdef";char* str(){printf("string=%s\n",a);return a;}int b;int num(){b=20000;printf("number=%d\n",b);return b;}
C数组传到lua:
--lualocal ffi=require"ffi"local myffi = ffi.load('myffi')ffi.cdef[[int n[]; --定义一个全局变量数组,才能传递int main ();int add(int *l);]]myffi.main()myffi.add(myffi.n)
#include <stdio.h>int n[ 5390*9590 ]; /* n 是一个包含 10 个整数的数组 */int main (){int i;/* 初始化数组元素 */for ( i = 0; i < 5390*9590; i++ ){n[ i ] = i + 100; /* 设置元素 i 为 i + 100 */}/* 输出数组中每个元素的值 */return 0;}int add(int *l){int j;for (j = 0; j < 10; j++ ){printf("Element[%d] = %d\n", j, l[j] );}return 0;}
延时函数
local ffi=require"ffi"ffi.cdef[[void Sleep(int ms);int poll(struct pollfd *fds, unsigned long nfds, int timeout);]]local sleepif ffi.os == "Windows" thenfunction sleep(s)ffi.C.Sleep(s*1000)endelsefunction sleep(s)ffi.C.poll(nil, 0, s*1000)endendprint(ffi.os)for i=1,160 doio.write("."); io.flush()sleep(0.01)endio.write(".")
表初始化器
local ffi = require("ffi")ffi.cdef[[struct foo { int a, b; };union bar { int i; double d; };struct nested { int x; struct foo y; };]]ffi.new("int[3]", {}) --> 0, 0, 0ffi.new("int[3]", {1}) --> 1, 1, 1ffi.new("int[3]", {1,2}) --> 1, 2, 0ffi.new("int[3]", {1,2,3}) --> 1, 2, 3ffi.new("int[3]", {[0]=1}) --> 1, 1, 1ffi.new("int[3]", {[0]=1,2}) --> 1, 2, 0ffi.new("int[3]", {[0]=1,2,3}) --> 1, 2, 3ffi.new("int[3]", {[0]=1,2,3,4}) --> error: too many initializersffi.new("struct foo", {}) --> a = 0, b = 0ffi.new("struct foo", {1}) --> a = 1, b = 0ffi.new("struct foo", {1,2}) --> a = 1, b = 2ffi.new("struct foo", {[0]=1,2}) --> a = 1, b = 2ffi.new("struct foo", {b=2}) --> a = 0, b = 2ffi.new("struct foo", {a=1,b=2,c=3}) --> a = 1, b = 2 'c' is ignoredffi.new("union bar", {}) --> i = 0, d = 0.0ffi.new("union bar", {1}) --> i = 1, d = ?ffi.new("union bar", {[0]=1,2}) --> i = 1, d = ? '2' is ignoredffi.new("union bar", {d=2}) --> i = ?, d = 2.0ffi.new("struct nested", {1,{2,3}}) --> x = 1, y.a = 2, y.b = 3ffi.new("struct nested", {x=1,y={2,3}}) --> x = 1, y.a = 2, y.b = 3
参数化类型
为了促进某些抽象,两个函数 ffi.typeof和 ffi.cdef支持C声明中的参数化类型。注意:使用cdecl的其他API函数均不允许这样做。
您可以在声明中写typedef名称, 标识符或数字的任何地方,都可以改写 $(美元符号)。这些占位符按出现顺序替换为cdecl字符串后的参数:
--声明具有参数化字段类型和名称的结构:ffi.cdef([[typedef struct { $ $; } foo_t;]], type1, name1)--具有动态名称的匿名结构:local bar_t = ffi.typeof("struct { int $, $; }", name1, name2)--派生的指针类型:local bar_ptr_t = ffi.typeof("$ *", bar_t)--即使在VLA不起作用的地方,参数化尺寸也可以工作:local matrix_t = ffi.typeof("uint8_t[$][$]", width, height)
cdata对象的垃圾收集
请注意,指针本身是cdata对象,但是垃圾收集器不会跟随它们。因此,例如,如果将cdata数组分配给指针,则只要指针仍在使用中,就必须保持持有该数组的cdata对象处于活动状态:
ffi.cdef[[typedef struct { int *a; } foo_t;]]local s = ffi.new("foo_t", ffi.new("int[10]")) -- 错误!local a = ffi.new("int[10]") -- OKlocal s = ffi.new("foo_t", a)-- 现在对's'进行操作,但保持'a'存活直到完成。
—C语言里,只能储存数值,所以任何类型都转成地址,再传到C函数里,读取数组里的地址来获取其他数组内容。
a = ffi.new("char[100]",'daslkhdasl') --char a[100]='daslkhdasl'c = ffi.new("char[100]", 'nnncncncncc')--c = ffi.new("char[100]", {'n','n','n','\0'}) --字符串--c = ffi.new("int[100]", {1,2,3,4,5}) --数值local p = ffi.cast('char*', a) -- char *p = a[100] 转指针local p1 = ffi.cast('char*', c)b = ffi.new("int[100]", {tonumber(p),tonumber(p1)}) --储存 a[100] 指针地址myffi.main(b)
#include <stdint.h> --解决警告:将一个整数转换为大小不同的指针 调用 uintptr_t 类型int main(int *a) {printf("%s\n",a[1]); --读取地址 输出 'nnncncncncc'--int *p =(int *)(uintptr_t)a[1]; --uintptr_t是解决警告,数值 转 指针用--printf("%s\n",p[1]); --读取地址 输出 2return 0;}
local diff={"0x000400-0x333333", "0x000400-0x333333"}local t ={}for k,v in pairs(diff) doif type(v)=="string" thenlocal p = ffi.cast('char*', ffi.new("char[100]",v))table.insert(t,tonumber(p))endendlocal b = ffi.new("int[100]", t)--b = {地址1,地址2}
c y=0, x=0
yx距离+x
_BINARIZE_Image[(yrect[2]-rect[0])+x]
lua  一维表转二维表 i=一维表第n个
y=取整(i/x距离)+1,x=x
ti[math.floor(i/(rect[3]-rect[1]))+1][x]
-- logcat(ffi.string(libhello.str)) --需要转换才能提取c文件里的字符串
/* int diff1[]={10,11,10111}; //一维表int diff2[]={12,13,10222};int diff3[]={14,15,10333};+unsigned int p1 = (unsigned int)diff1; //把指针转为数值,存入数据到数组unsigned int p2 = (unsigned int)diff2;unsigned int p3 = (unsigned int)diff3; *//* for(y = rect[1]; y<rect[3]+1; y++) { //遍历图片指定范围像素点for(x = rect[0]; x<rect[2]+1; x++) {printf("%d,%d\r\n",x,y);int co,ko,s;co=16711935; //当前颜色值ko=-5919833; //开发颜色值s = 12; //相似度阈值if (get_color_PK(str1,str_num1,co,ko,s)==0) { //比色 0成功 -1失败printf("匹配\r\n");}}} */
不明觉厉。。

