这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战
之前我们知道了Dart如何调用C的函数,那么C函数如何能调用Dart函数呢。下面我们通过示例来了解一下。
C调Dart函数
简单示例
原理: C本身是没有提供调用Dart函数的方法的,但是我们可以在程序启动后通过Dart将函数当做参数传入C中,C中缓存起来Dart的函数指针,就可以在需要的时候实现C调用Dart。
首先,我们先在Dart上定义一个函数。需要注意的是Dart函数需要是顶级函数或者静态函数才能被调用,否则会报错.
void dartFunction() {
debugPrint("[Dart]: Dart 函数被调用了");
}
我们在C中定义一个注册函数 sample.h
void callDart(void (*callback)());
sample.c
void callDart(void (*callback)()) {
printf("[CPP]: 现在调用Dart函数");
callback();
}
其中的callback就是接收到的Dart的函数,这里我们为了看效果,就在注册后直接调用Dart函数了。
然后我们将Dart函数转换成Pointer
类型,并通过调用C的callDart
函数传入到C中。
late final _callDartPtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>>(
'callDart');
late final _callDart = _callDartPtr.asFunction<
void Function(ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>)>();
_callDart(ffi.Pointer.fromFunction(dartFunction));
这里,我们试用结果ffi.Pointer.fromFunction
方法将Dart函数转换成C函数指针的Dart映射,然后通过_callDart
来调用C的callDart
函数。
运行后输出:
[CPP]: 现在调用Dart函数
[Dart]: Dart 函数被调用了
成功!
带参数的Dart函数
C如何调用带参数的Dart函数呢,我们下面来定义一个Dart函数
static void add(int num1,int num2) {
print("[Dart]: num1: ${num1}, num2: ${num2}");
}
上面函数被调用后会输出num1
、num2
的值。
然后我们改造一下callDart
函数
sample.h
void callDart(void (*callback)(), void (*add)(int, int));
sample.c
void callDart(void (*callback)(), void (*add)(int, int)) {
printf("现在调用Dart函数");
callback();
printf("调用Dart Add函数");
add(1, 2);
}
dart端
late final _callDartPtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Void Function(ffi.Int32, ffi.Int32)>>)>>('callDart');
late final _callDart = _callDartPtr.asFunction<
void Function(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>,
ffi.Pointer<
ffi.NativeFunction<ffi.Void Function(ffi.Int32, ffi.Int32)>>)>();
_callDart(ffi.Pointer.fromFunction(DartFunctions.dartFunction),ffi.Pointer.fromFunction(DartFunctions.add));
返回输出
[CPP]: 现在调用Dart函数
[Dart]: Dart 方法被调用了
[CPP]: 调用Dart Add函数
[Dart]: num1: 1, num2: 2
这样,参数就从C传到Dart端了。
获取返回值
上面的示例都只是调用Dart函数,并没有从Dart端获取返回值。我们再来改造一下add
方法,让它可以返回num1
num2
相加的值。
static int add(int num1, int num2) {
return num1 + num2;
}
sample.h
void callDart(void (*callback)(), int (*add)(int, int));
sample.c
void callDart(void (*callback)(), int (*add)(int, int)) {
printf("现在调用Dart函数");
callback();
printf("调用Dart Add函数");
int result = add(1, 2);
printf("Add 结果 %d", result);
}
main.dart
late final _callDartPtr = _lookup<
ffi.NativeFunction<
ffi.Void Function(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>,
ffi.Pointer<
ffi.NativeFunction<
ffi.Int32 Function(ffi.Int32, ffi.Int32)>>)>>('callDart');
late final _callDart = _callDartPtr.asFunction<
void Function(
ffi.Pointer<ffi.NativeFunction<ffi.Void Function()>>,
ffi.Pointer<
ffi.NativeFunction<ffi.Int32 Function(ffi.Int32, ffi.Int32)>>)>();
_callDart(ffi.Pointer.fromFunction(DartFunctions.dartFunction),ffi.Pointer.fromFunction(DartFunctions.add, 0));
需要注意的是,如果Dart函数有返回值,fromFunction
的第二个参数就需要传入当出错时返回的值。
输出结果
[CPP]: 现在调用Dart函数
[Dart]: Dart 方法被调用了
[CPP]: 调用Dart Add函数
[Dart]: num1: 1, num2: 2
[CPP]: Add 结果 3
好了,现在我们就学会了如何使用C调用Dart函数了。当然实际项目中,我们一般需要定义一个初始函数,把想要C调用的Dart函数传入到C的内存中,在C需要的时候调用。
上面代码我都提交到我的Github仓库中,有学习需要自取,传送门