Dart --> Native
Dart同步调用Native方法
Dart FFI函数的声明
// Declaration
final int Function(int x, int y) nativeAdd = nativeInteropLib
.lookup<NativeFunction<Int32 Function(Int32, Int32)>>("native_add")
.asFunction();
Dart FFI函数的使用
// Usage
print('nativeAdd(1, 2) = ${nativeAdd(1, 2)}');
FFI函数的Native实现
Native方法需要暴露C接口
// Implementation
__attribute__((visibility("default"))) __attribute__((used))
int32_t native_add(int32_t a, int32_t b) {
printf("native_add called\n"); // XCode debug print
return a + b;
}
Native --> Dart
Dart同步调用Native方法,并Native同步回调Dart方法
Dart FFI函数的声明
// Declaration
typedef NativeSyncCallbackFunc = Int32 Function(Int32 n);
typedef _c_NativeSyncCallback = Void Function(
Pointer<NativeFunction<NativeSyncCallbackFunc>> callback,
);
typedef _dart_NativeSyncCallback = void Function(
Pointer<NativeFunction<NativeSyncCallbackFunc>> callback,
);
final _dart_NativeSyncCallback nativeSyncCallback = nativeInteropLib
.lookup<NativeFunction<_c_NativeSyncCallback>>("NativeSyncCallback")
.asFunction();
Dart回调函数的声明
Dart回调函数需要是top-level函数
// Declaration
int normalSyncCallback(int n) {
print('normalSyncCallback called');
return n * n;
}
Dart FFI函数的使用
// Usage
var normalFunc = Pointer.fromFunction<NativeSyncCallbackFunc>(normalSyncCallback, syncExceptionalReturn);
nativeSyncCallback(normalFunc);
FFI函数的Native实现
C++实现需要暴露C接口
// Implementation
#ifdef __cplusplus
extern "C" {
#endif
typedef int32_t (*CallbackFunc)(int32_t n);
__attribute__((visibility("default"))) __attribute__((used))
void NativeSyncCallback(CallbackFunc callback) {
std::cout << "NativeSyncCallback callback(9) = " << callback(9) << std::endl; // XCode debug print
}
#ifdef __cplusplus
}
#endif
Native -async-> Dart
Dart同步调用Native方法,并Native异步回调Dart方法
Dart FFI函数的声明
// Declar
typedef NativeAsyncCallbackFunc = Void Function();
typedef _c_NativeAsyncCallback = Void Function(
Pointer<NativeFunction<NativeAsyncCallbackFunc>> callback,
);
typedef _dart_NativeAsyncCallback = void Function(
Pointer<NativeFunction<NativeAsyncCallbackFunc>> callback,
);
final _dart_NativeAsyncCallback nativeAsyncCallback = nativeInteropLib
.lookup<NativeFunction<_c_NativeAsyncCallback>>("NativeAsyncCallback")
.asFunction();
Dart回调函数的声明
Dart回调函数需要是top-level函数
// Declaration
void asyncCallback() {
print('asyncCallback called');
}
Dart FFI函数的使用
// Usage
var asyncFunc = Pointer.fromFunction<NativeAsyncCallbackFunc>(asyncCallback);
nativeAsyncCallback(asyncFunc);
FFI函数的Native实现
Dart回调函数执行需要在发起转换(即fromFunction)的Dart Isolate的Mutator Thread执行,所以必须在Native侧,把Dart回调函数指针通过SendPort发回Mutator Thread,然后转换执行
初始化Dart Dynamic Library API
- Dart声明
// Declaration
final _initializeApi = nativeInteropLib.lookupFunction<
IntPtr Function(Pointer<Void>),
int Function(Pointer<Void>)>("InitDartApiDL");
- Dart使用
// Usage
WidgetsFlutterBinding.ensureInitialized();
var nativeInited = _initializeApi(NativeApi.initializeApiDLData);
- Native声明
// Declaration
DART_EXTERN intptr_t Dart_InitializeApiDL(void* data);
注册SendPort
- Dart声明
// Declaration
final _registerSendPort = nativeInteropLib.lookupFunction<
Void Function(Int64 sendPort),
void Function(int sendPort)>('RegisterSendPort');
- Dart使用
// Usage
_registerSendPort(_receivePort.sendPort.nativePort);
- Native实现
// Implementaion
Dart_Port send_port_;
DART_EXPORT void RegisterSendPort(Dart_Port send_port) {
send_port_ = send_port;
}
Dart FFI函数的Native实现
// Implementation
DART_EXPORT void NativeAsyncCallback(VoidCallbackFunc callback) {
printf("NativeAsyncCallback Running on (%p)\n", pthread_self());
pthread_t callback_thread;
pthread_create(&callback_thread, NULL, thread_func, (void *)callback);
}
Native发送回调函数指针给Dart
void *thread_func(void *args) {
printf("thread_func Running on (%p)\n", pthread_self());
sleep(1 /* seconds */); // doing something
Dart_CObject dart_object;
dart_object.type = Dart_CObject_kInt64;
dart_object.value.as_int64 = reinterpret_cast<intptr_t>(args);
Dart_PostCObject_DL(send_port_, &dart_object);
pthread_exit(args);
}
Dart接收回调函数指针
void _handleNativeMessage(dynamic message) {
print('_handleNativeMessage $message');
final int address = message;
_executeCallback(Pointer<Void>.fromAddress(address).cast());
}
执行回调函数
因为函数指针为Native指针,目前无法还原为Dart函数,需要传递到Native侧执行
- Dart声明
// Declaration
final _executeCallback = nativeInteropLib.lookupFunction<_c_NativeAsyncCallback,
_dart_NativeAsyncCallback>('ExecuteCallback');
- Dart使用
// Usage
_executeCallback(Pointer<Void>.fromAddress(address).cast());
- Native实现
// Implementaion
DART_EXPORT void ExecuteCallback(VoidCallbackFunc callback) {
printf("ExecuteCallback Running on (%p)\n", pthread_self());
callback();
}
可以看到NativeAsyncCallback和ExecuteCallback是在同一线程,即Dart Isolate的Mutator线程,而thread_func执行在另一个线程
Native -messge-> Dart
一般情况下,更多使用message的方式给Dart侧传递消息,让Dart侧自行决定回调的处理方式,类似Flutter的MessageChannel
- 消息定义
// Declaration
class CppResponse {
final int pendingCall;
final Uint8List data;
CppResponse(this.pendingCall, this.data);
List toCppMessage() => List.from([pendingCall, data], growable: false);
String toString() => 'CppResponse(message: ${data.length})';
}
- 消息使用
void handleCppRequests(dynamic message) {
final cppRequest = CppRequest.fromCppMessage(message);
print('Dart: Got message: $cppRequest');
if (cppRequest.method == 'myCallback1') {
// Use the data in any way you like. Here we just take the first byte as
// the argument to the function.
final int argument = cppRequest.data[0];
final int result = myCallback1(argument);
final cppResponse =
CppResponse(cppRequest.pendingCall!, Uint8List.fromList([result]));
print('Dart: Responding: $cppResponse');
cppRequest.replyPort!.send(cppResponse.toCppMessage());
} else if (cppRequest.method == 'myCallback2') {
final int argument = cppRequest.data[0];
myCallback2(argument);
}
}