ffi_plugin
TSL语言的跨平台实现的外部函数接口(Foreign Function Interface)插件。
安装
(已集成到mytsl
发行版中)
动态库文件:Windows: ffi_plugin.dll, Linux: libffi_plugin.so。
把相关的动态库文件拷贝到执行服务器或者TSL目录的plugin目录。
使用指南
提供的TSL函数:
ffi_cb_def
ffi_cb_def(return_var, callback_name, ...args)
: 定义回调函数原型。
-
参数列表
参数 描述 return_var 返回值类型定义,魔法参数类型。 callback_name 回调原型名称,字符串类型。 args 参数类型,魔法参数类型。 -
返回值
数组类型,如果发生错误:
下标 值 0 错误代码 1 错误信息 没有错误:
下标 值 0 0 -
支持的类型定义
类型 描述 i8 有符号8位整数 i16 有符号16位整数 i32 有符号32位整数 i64 有符号64位整数 u8 无符号8位整数 u16 无符号8位整数 u32 无符号8位整数 u64 无符号8位整数 f32 32位浮点数 f64 64位浮点数 void 空 pointer 指针 char 8位字符 int 有符号32位整数 foat 32位浮点数 doble 64位浮点数 intptr 指针 例子:
ffi_cb_alloc
ffi_cb_alloc(callback_name, func)
: 分配回调指针。
-
参数列表
参数 描述 callback_name 回调原型名称,字符串类型。 func 函数,lambda或者字符串类型 -
返回值
数组类型,如果发生错误:
下标 值 0 错误代码 1 错误信息 没有错误:
下标 值 0 0 1 回调指针
ffi_cb_free
ffi_cb_free(pointer)
: 释放回调指针。
-
参数列表
参数 描述 pointer 回调指针。 -
返回值 1
ffi_new
ffi_new(type_def, [vaule])
: 分配系统内存。
-
参数列表
参数 描述 type_def 类型定义,魔法参数类型。 vaule 初始值,可选参数。 类型定义参见ffi_cb_def。可以同时指定要分配的类型的个数,像数组一样。
例如:
[err, x] := ffi_new(@int()); // x = int[1],总共4个字节 [err,x] := ffi_new(@int(10)); // x = int[10],总共4*10个字节
ffi_new还支持定义struct类的结构,例如:
st_def := @struct( @i32("i1") , @i32("i2") , @i8("i3") , @float("f1") , @double("d1") , @char("s1", 16) // 相当于C的 char s1[16] ) -> "<1"; // 1字节对齐,小端字节序模式。如果不设置,用系统默认设置。 [err, st] := ffi_new(st_def); st.i1 := 1; st.i2 := 2; st.i3 := 3; st.f1 := 12.34; st.d1 := 56.78; st.s1 := "1234567890"; [err, data] := ffi_pack(st); // 用ffi_pack把结构输出成二进制类型
-
返回值
数组类型,如果发生错误:
下标 值 0 错误代码 1 错误信息 没有错误:
下标 值 0 0 1 系统内存对象
Note
分配的系统内存是自动管理的,和相应变量生命周期一样。
系统内存对象的相关方法
value()
value()
: 返回TSL格式的变量。
例如:
[err, x] :=ffi_new(@int(), 1);
vprintln(x.value()); // 打印:1
[err, x] :=ffi_new(@int(10), 1);
vprintln(x.value()); // 打印:array(1,1,1,1,1,1,1,1,1,1)
[err, x] :=ffi_new(@char(12), "hello world");
vprintln(x.value()); // 打印:hello world
string()
: 返回字符串。
ffi_pack
ffi_pack(struct)
: 将结构转成二进制类型。
-
参数列表
参数 描述 struct 结构对象。 例如:
-
返回值
数组类型,如果发生错误:
下标 值 0 错误代码 1 错误信息 没有错误:
下标 值 0 0 1 二进制类型
ffi_unpack
ffi_unpack(struct_def, data)
: 将二进制类型或者字符串类型转成结构。
-
参数列表
参数 描述 struct_def 结构定义,魔法参数类型。 data 数据,二进制类型或者字符串类型 例如:
-
返回值
数组类型,如果发生错误:
下标 值 0 错误代码 1 错误信息 没有错误:
下标 值 0 0 1 结构对象
ffi_typeof
ffi_typeof(struct_def | struct)
: 输出结构的定义。
-
参数列表
参数 描述 struct_def 结构定义,魔法参数类型。也可以是结构对象。 例如:
st_def := @struct( @i32("i1") , @i32("i2") , @i8("i3") , @float("f1") , @double("d1") ); [err, st_info] := ffi_typeof(st_def); println("{}", st_info); // 打印: array("type":"struct","size":24L,"alignment":8,"field":(("i1","int",1,4L,0L),("i2","int",1,4L,4L),("i3","i8",1,1L,8L),("f1","float",1,4L,12L),("d1","f64",1,8L,16L)))
-
返回值
数组类型,如果发生错误:
下标 值 0 错误代码 1 错误信息 没有错误:
下标 值 0 0 1 数组类型,下标"type"是类型,下标"size"是结构总共占用字节数,下标"alignment"是对齐方式,下标"field"是包含的字段。 结果数组"field"子项的内容: | 下标 | 值 | |:----|:----| |0|字段名| |1|类型| |2|个数| |3|占用字节数| |4|起始位置|
ffi_sizeof
ffi_sizeof(mem|struct|@struct.field)
: 输出结构的定义。
-
参数列表
参数 描述 mem 系统内存对象,也可以是结构对象或者结构对象的字段的地址。 例如:
st_def := @struct( @i32("i1") , @i32("i2") , @i8("i3") , @float("f1") , @double("d1") ); [err, size] := ffi_sizeof(st_def); [err, st] := ffi_new(@st_def); [err, size] := ffi_sizeof(st); [err, size] := ffi_sizeof(@st.f1); // 用@struct.field来取结构字段的地址 [err, p] := ffi_new(@int()); [err, size] := ffi_sizeof(p); [err, size] := ffi_sizeof(@int());
-
返回值
数组类型,如果发生错误:
下标 值 0 错误代码 1 错误信息 没有错误:
下标 值 0 0 1 大小,整数类型。
ffi_copy
ffi_copy(dst, src, [len] )
: 内存拷贝,功能类似C的memcpy。
-
参数列表
参数 描述 dst 系统内存对象,也可以是结构对象或者结构对象的字段的地址。 src 系统内存对象,也可以是结构对象或者结构对象的字段的地址。 len 长度,整数类型,可选参数。 例如:
-
返回值
数组类型,如果发生错误:
下标 值 0 错误代码 1 错误信息 没有错误:
下标 值 0 0 1 拷贝的字节数,整数类型。
ffi_fill
ffi_fill(dst, len, [c] )
: 内存填充,功能类似C的memset。
-
参数列表
参数 描述 dst 系统内存对象,也可以是结构对象或者结构对象的字段的地址。 src 系统内存对象,也可以是结构对象或者结构对象的字段的地址。 len 长度,整数类型,可选参数。 例如:
-
返回值
数组类型,如果发生错误:
下标 值 0 错误代码 1 错误信息 没有错误:
下标 值 0 0 1 填充的字节数,整数类型。
范例
EnumWindows回调
// 定义回调原型
ffi_cb_def(@i32(), "EnumWindowsProc", @pointer(), @intptr());
// 分配回调指针
[err, cb] := ffi_cb_alloc("EnumWindowsProc",
function(h, p)
begin
println("h={},p={}", h, p);
[err, buffer] := ffi_new(@char(512)); // 分配512字节接收ClassName
pp := GetClassNameA(h, buffer, 512);
vprintln(pp, buffer.string());
return 1;
end);
EnumWindows(cb, 0);
// 使用完释放回调指针
ffi_cb_free(cb);
function EnumWindows(proc:pointer;param:pointer):int;stdcall;external "User32.dll" name "EnumWindows";
function GetClassNameA(HH:pointer;var name:string;len:integer):pointer;stdcall;external "User32.dll" name "GetClassNameA";
附录
更新历史
- 2022-8-23 初始发布。