连接到动态库

连接到动态库

注意: 下面的示例主要针对的是使用Golang生成的动态库

生成动态库

使用Go参数

// 你需要导入C
import "C"

// 在需要导出的动态库上添加export注解,注意export前面没有空格,函数名开头大写

//export Run
func Run(data string){
  // 你的函数内容
}

// 添加一个空的主函数
func main(){}

使用C语言参数或有返回值

// 你需要导入C
import "C"

// 在需要导出的动态库上添加export注解,注意export前面没有空格,函数名开头大写

//export Add
func Add(num1 C.int, num2 C.int) C.int {
	return num1 + num2
}

使用C语言字符串参数

// 你需要导入C
import "C"

// 在需要导出的动态库上添加export注解,注意export前面没有空格,函数名开头大写

//export Connect
func Connect(s1 *C.char, s2 *C.char) *C.char {
	gs1 := C.GoString(s1)
	gs2 := C.GoString(s2)

	return C.CString(gs1 + " " + gs2)
}

导出动态库

通过下面的命令导出动态库

# macOS & iOS
go build -o lib.dylib -buildmode=c-shared main.go
# Windows
go build -o lib.dll -buildmode=c-shared main.go

将动态库打包到App内部

可以参考官方文档

  • macOS
  • iOS
  • Android
  • Windows系统只需要将动态库复制到输出的根目录就可以了

连接到动态库 (Go类型)

将动态库存储为Dart函数

import 'dart:ffi';

// 对于Golang的字符串,需要构造一个GoString类型
base class GoString extends Struct {
  external Pointer<Utf8> p;
  @IntPtr()
  external int n;
}

// 添加一个方法将String转换成GoString
GoString param(String data){
  final str = data.toNativeUtf8();
  final goString = malloc<GoString>();
  goString.ref.p = str;
  goString.ref.n = str.length;
  return goString.ref;
}

// 定义类型,一个为动态库函数,一个为Dart函数,注意这两个类型完全不同
typedef Run = void Function(GoString, GoString, GoString, GoString);
typedef RunFunc = Void Function(GoString, GoString, GoString, GoString);

// 绑定动态库
final dynamicLib=DynamicLibrary.open(Platform.isMacOS ? 'lib.dylib' : 'lib.dll');

// 绑定函数
final Run run=dynamicLib
.lookup<NativeFunction<RunFunc>>('Run')
.asFunction();

运行函数

// 注意,如果是一个会阻塞的函数会导致整个Flutter阻塞,因此确保不会阻塞Flutter主线程
run(param("hello world!"));

// 如果是类似于运行服务器这种需要新开线程的情况需要使用Isolate

static void isolateFunction(List params){
  GoString param0 = param(params[0]);
  GoString param1 = param(params[1]);
  final dynamicLib=DynamicLibrary.open(Platform.isMacOS ? 'lib.dylib' : 'lib.dll');
  final Run run=dynamicLib
  .lookup<NativeFunction<RunFunc>>('Run')
  .asFunction();

  run(param0, param1);
}

await Isolate.spawn(isolateFunction, [param1, param2]);

连接到动态库(C类型)

将动态库存储为Dart函数

import 'dart:ffi';

// 定义类型,一个为动态库函数,一个为Dart函数,注意这两个类型完全不同
typedef Add = int Function(int, int);
typedef AddFunc = Int Function(Int, Int);

// 绑定动态库
final dynamicLib=DynamicLibrary.open(Platform.isMacOS ? 'lib.dylib' : 'lib.dll');

// 绑定函数
final Add add=dynamicLib
.lookup<NativeFunction<AddFunc>>('Add')
.asFunction();

运行函数

print(run(3, 4));
// 输出7

连接到动态库(C语言字符串)

将动态库存储为Dart函数

import 'dart:ffi';
import 'package:ffi/ffi.dart';

typedef Connect = Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>);
typedef ConnectFunc=Pointer<Utf8> Function(Pointer<Utf8>, Pointer<Utf8>);

final dylib = DynamicLibrary.open("server.dylib");
final Connect connect=dylib
.lookup<NativeFunction<ConnectFunc>>("Connect")
.asFunction();

运行函数

print(connect("Hello".toNativeUtf8(), "world!".toNativeUtf8()).toDartString());