Lua ffi - 图2

Lua ffi

所有传递到lua的变量都必须在C里定义全局变量:

  1. ffi.cdef[[ --[]数组变量大小可以不填
  2. int n[]; --定义一个全局变量,才能传递
  3. int num; --数值
  4. int str[]; --字符串、数组都是这种
  5. ]]

关于C头文件:

  1. #include <stdio.h> --使用 printf 函数必须加
  2. #include <string.h> --使用 strcpy 函数必须加


实例:
Lua传参到C,并修改后返回:

  1. --myffi.c
  2. #include <string.h>
  3. #include <stdio.h>
  4. char str(char* L)
  5. {
  6. printf("string=%s\n",L);
  7. printf("string*=%p\n",L);
  8. strcpy(L,"abc "); --修改字符串 需要#include <string.h>
  9. return 0;
  10. }
  11. int num(int L)
  12. {
  13. printf("number=%d\n",L);
  14. printf("number*=%p\n",L);
  15. int b = 2200;
  16. return L+b;
  17. }
  1. --hello.lua
  2. local ffi=require"ffi"
  3. local myffi = ffi.load('myffi')
  4. ffi.cdef[[
  5. char str(char* L);
  6. int num(int L);
  7. ]]
  8. local a="人鱼"
  9. local b=1100
  10. --传入地址
  11. -- local p = ffi.cast('char*', a)
  12. -- myffi.str(p)
  13. -- print("a="..a)
  14. -- local p = ffi.cast('int', b)
  15. -- b=myffi.num(p)
  16. -- 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 ffi - 图3
运行:
./lua-5.1.5/src/lua hello.lua

C++例子

  1. //myffi.cpp
  2. #include <iostream>
  3. using namespace std;
  4. int main()
  5. {
  6. cout << "Hello, world111111111111!" << endl;
  7. return 0;
  8. }
  9. //hello.lua
  10. local ffi=require"ffi"
  11. local myffi = ffi.load('myffi')
  12. ffi.cdef[[
  13. int main();
  14. ]]
  15. myffi.main()

编译
g++ -m32 -g -o myffi.dll -fpic -shared myffi.cpp

C传参到Lua:

  1. --lua
  2. local ffi=require"ffi"
  3. local myffi = ffi.load('myffi')
  4. ffi.cdef[[
  5. char a[]; --C语言里面全局变量,才可以返回值
  6. char* str(); --字符串返回指针
  7. int b; --C语言里面全局变量,才可以返回值
  8. int num(); --数值直接返回
  9. ]]
  10. a=myffi.str()
  11. print(ffi.string(a)) --类型cdata 指针 转换成 String
  12. b=myffi.num()
  13. print(b)
  1. --c
  2. char a[]="abcdef";
  3. char* str()
  4. {
  5. printf("string=%s\n",a);
  6. return a;
  7. }
  8. int b;
  9. int num()
  10. {
  11. b=20000;
  12. printf("number=%d\n",b);
  13. return b;
  14. }

C数组传到lua:

  1. --lua
  2. local ffi=require"ffi"
  3. local myffi = ffi.load('myffi')
  4. ffi.cdef[[
  5. int n[]; --定义一个全局变量数组,才能传递
  6. int main ();
  7. int add(int *l);
  8. ]]
  9. myffi.main()
  10. myffi.add(myffi.n)
  1. #include <stdio.h>
  2. int n[ 5390*9590 ]; /* n 是一个包含 10 个整数的数组 */
  3. int main ()
  4. {
  5. int i;
  6. /* 初始化数组元素 */
  7. for ( i = 0; i < 5390*9590; i++ )
  8. {
  9. n[ i ] = i + 100; /* 设置元素 i 为 i + 100 */
  10. }
  11. /* 输出数组中每个元素的值 */
  12. return 0;
  13. }
  14. int add(int *l)
  15. {
  16. int j;
  17. for (j = 0; j < 10; j++ )
  18. {
  19. printf("Element[%d] = %d\n", j, l[j] );
  20. }
  21. return 0;
  22. }

延时函数

  1. local ffi=require"ffi"
  2. ffi.cdef[[
  3. void Sleep(int ms);
  4. int poll(struct pollfd *fds, unsigned long nfds, int timeout);
  5. ]]
  6. local sleep
  7. if ffi.os == "Windows" then
  8. function sleep(s)
  9. ffi.C.Sleep(s*1000)
  10. end
  11. else
  12. function sleep(s)
  13. ffi.C.poll(nil, 0, s*1000)
  14. end
  15. end
  16. print(ffi.os)
  17. for i=1,160 do
  18. io.write("."); io.flush()
  19. sleep(0.01)
  20. end
  21. io.write(".")

表初始化器

  1. local ffi = require("ffi")
  2. ffi.cdef[[
  3. struct foo { int a, b; };
  4. union bar { int i; double d; };
  5. struct nested { int x; struct foo y; };
  6. ]]
  7. ffi.new("int[3]", {}) --> 0, 0, 0
  8. ffi.new("int[3]", {1}) --> 1, 1, 1
  9. ffi.new("int[3]", {1,2}) --> 1, 2, 0
  10. ffi.new("int[3]", {1,2,3}) --> 1, 2, 3
  11. ffi.new("int[3]", {[0]=1}) --> 1, 1, 1
  12. ffi.new("int[3]", {[0]=1,2}) --> 1, 2, 0
  13. ffi.new("int[3]", {[0]=1,2,3}) --> 1, 2, 3
  14. ffi.new("int[3]", {[0]=1,2,3,4}) --> error: too many initializers
  15. ffi.new("struct foo", {}) --> a = 0, b = 0
  16. ffi.new("struct foo", {1}) --> a = 1, b = 0
  17. ffi.new("struct foo", {1,2}) --> a = 1, b = 2
  18. ffi.new("struct foo", {[0]=1,2}) --> a = 1, b = 2
  19. ffi.new("struct foo", {b=2}) --> a = 0, b = 2
  20. ffi.new("struct foo", {a=1,b=2,c=3}) --> a = 1, b = 2 'c' is ignored
  21. ffi.new("union bar", {}) --> i = 0, d = 0.0
  22. ffi.new("union bar", {1}) --> i = 1, d = ?
  23. ffi.new("union bar", {[0]=1,2}) --> i = 1, d = ? '2' is ignored
  24. ffi.new("union bar", {d=2}) --> i = ?, d = 2.0
  25. ffi.new("struct nested", {1,{2,3}}) --> x = 1, y.a = 2, y.b = 3
  26. ffi.new("struct nested", {x=1,y={2,3}}) --> x = 1, y.a = 2, y.b = 3

参数化类型

为了促进某些抽象,两个函数 ffi.typeofffi.cdef支持C声明中的参数化类型。注意:使用cdecl的其他API函数均不允许这样做。
您可以在声明中写typedef名称标识符数字的任何地方,都可以改写 $(美元符号)。这些占位符按出现顺序替换为cdecl字符串后的参数:

  1. --声明具有参数化字段类型和名称的结构:
  2. ffi.cdef([[
  3. typedef struct { $ $; } foo_t;
  4. ]], type1, name1)
  5. --具有动态名称的匿名结构:
  6. local bar_t = ffi.typeof("struct { int $, $; }", name1, name2)
  7. --派生的指针类型:
  8. local bar_ptr_t = ffi.typeof("$ *", bar_t)
  9. --即使在VLA不起作用的地方,参数化尺寸也可以工作:
  10. local matrix_t = ffi.typeof("uint8_t[$][$]", width, height)

cdata对象的垃圾收集

请注意,指针本身是cdata对象,但是垃圾收集器不会跟随它们。因此,例如,如果将cdata数组分配给指针,则只要指针仍在使用中,就必须保持持有该数组的cdata对象处于活动状态:

  1. ffi.cdef[[
  2. typedef struct { int *a; } foo_t;
  3. ]]
  4. local s = ffi.new("foo_t", ffi.new("int[10]")) -- 错误!
  5. local a = ffi.new("int[10]") -- OK
  6. local s = ffi.new("foo_t", a)
  7. -- 现在对's'进行操作,但保持'a'存活直到完成。

—C语言里,只能储存数值,所以任何类型都转成地址,再传到C函数里,读取数组里的地址来获取其他数组内容。

  1. a = ffi.new("char[100]",'daslkhdasl') --char a[100]='daslkhdasl'
  2. c = ffi.new("char[100]", 'nnncncncncc')
  3. --c = ffi.new("char[100]", {'n','n','n','\0'}) --字符串
  4. --c = ffi.new("int[100]", {1,2,3,4,5}) --数值
  5. local p = ffi.cast('char*', a) -- char *p = a[100] 转指针
  6. local p1 = ffi.cast('char*', c)
  7. b = ffi.new("int[100]", {tonumber(p),tonumber(p1)}) --储存 a[100] 指针地址
  8. myffi.main(b)
  1. #include <stdint.h> --解决警告:将一个整数转换为大小不同的指针 调用 uintptr_t 类型
  2. int main(int *a) {
  3. printf("%s\n",a[1]); --读取地址 输出 'nnncncncncc'
  4. --int *p =(int *)(uintptr_t)a[1]; --uintptr_t是解决警告,数值 指针用
  5. --printf("%s\n",p[1]); --读取地址 输出 2
  6. return 0;
  7. }
  1. local diff={"0x000400-0x333333", "0x000400-0x333333"}
  2. local t ={}
  3. for k,v in pairs(diff) do
  4. if type(v)=="string" then
  5. local p = ffi.cast('char*', ffi.new("char[100]",v))
  6. table.insert(t,tonumber(p))
  7. end
  8. end
  9. local b = ffi.new("int[100]", t)
  10. --b = {地址1,地址2}

c y=0, x=0
yx距离+x
_BINARIZE_Image[(y
rect[2]-rect[0])+x]

lua 一维表转二维表 i=一维表第n个
y=取整(i/x距离)+1,x=x
ti[math.floor(i/(rect[3]-rect[1]))+1][x]

  1. -- logcat(ffi.string(libhello.str)) --需要转换才能提取c文件里的字符串
  1. /* int diff1[]={10,11,10111}; //一维表
  2. int diff2[]={12,13,10222};
  3. int diff3[]={14,15,10333};
  4. +
  5. unsigned int p1 = (unsigned int)diff1; //把指针转为数值,存入数据到数组
  6. unsigned int p2 = (unsigned int)diff2;
  7. unsigned int p3 = (unsigned int)diff3; */
  8. /* for(y = rect[1]; y<rect[3]+1; y++) { //遍历图片指定范围像素点
  9. for(x = rect[0]; x<rect[2]+1; x++) {
  10. printf("%d,%d\r\n",x,y);
  11. int co,ko,s;
  12. co=16711935; //当前颜色值
  13. ko=-5919833; //开发颜色值
  14. s = 12; //相似度阈值
  15. if (get_color_PK(str1,str_num1,co,ko,s)==0) { //比色 0成功 -1失败
  16. printf("匹配\r\n");
  17. }
  18. }
  19. } */

Lua ffi - 图4不明觉厉。。