1, fair 插件 是源代码
fair插件的 podspec中配置了一个动态库
s.vendored_frameworks = 'FairDynamicFlutter/Products/FairDynamicFlutter.framework'
那么这里为什么做成动态库呢,而不像 插件的实现一样全部是源代码实现?
2, 我们看到这个 FairDynamicFlutter.framework 动态库的源代码也在fair项目里面
他的实现很简单。 就是实现了一个单例
方法的实现跳转到 代理执行。 等于是定义了一个 接口而已。
外面可以配置这个代理
按照代理的接口去落实具体的方法执行体。
/// FFI协议
@protocol FAIRFFIProtocol <NSObject>
/// 同步方法调用
/// @param args 参数
- (const char *)executeScriptSyncImpl:(char *)args;
@end
@interface FairDynamicFlutter : NSObject
@property (nonatomic, weak) id<FAIRFFIProtocol> delegate;
+ (instancetype)sharedInstance;
@end
那么这么做的目的是什么?
3,可以看到这个动态库,声明了一个c函数
/// 同步方法调用
FAIR_FFI_EXTERN const char *invokeJSCommonFuncSync(char *args);
const char *invokeJSCommonFuncSync(char *args) {
if ([FairDynamicFlutter sharedInstance].delegate &&
[[FairDynamicFlutter sharedInstance].delegate respondsToSelector:@selector(executeScriptSyncImpl:)]) {
return [[FairDynamicFlutter sharedInstance].delegate executeScriptSyncImpl:args];
}
return "";
}
正式如此, 这就是使用dart 的 ffi 特性。 可以直接调用 c 代码 的能力。
所以才有了 为什么要专门做一个动态库。
这个动态库只是定义了一个delegate,暴露接口,由fair 插件中配置具体的方法实现。
这就完成了 dart 直接调用 ios c 代码的功能。
4, ios 中c代码如何被调用 dart ffi实现方法如下
首先在ios 这边做一个动态库,实现如下
使用宏定义,暴露出给 dart 层可见:
#if defined(__cplusplus)
#define FAIR_FFI_EXTERN extern "C" __attribute__((visibility("default"))) __attribute__((used))
#else
#define FAIR_FFI_EXTERN extern __attribute__((visibility("default"))) __attribute__((used))
#endif
c 代码的函数声明 部分,在头文件完成:
使用 extern "C" 表明这是 c 代码。 编译器在c++环境编译下,c++的函数符号编码 和 c 函数符号编码的不一样,使用extern c表示使用c的函数符号编译。
使用 attribute((visibility("default"))) attribute((used)) 这个就是 dart ffi 那边要求的暴露接口的声明方式,固定的模式。
/// 同步方法调用
FAIR_FFI_EXTERN const char *invokeJSCommonFuncSync(char *args);
c方法实现部分:
/// @param args 参数
/// @return 返回值
const char *invokeJSCommonFuncSync(char *args) {
if ([FairDynamicFlutter sharedInstance].delegate &&
[[FairDynamicFlutter sharedInstance].delegate respondsToSelector:@selector(executeScriptSyncImpl:)]) {
return [[FairDynamicFlutter sharedInstance].delegate executeScriptSyncImpl:args];
}
return "";
}
在 dart 测实现代码如下:
使用 ffi 库, DynamicLibrary 系统对象。 完成对 c 代码 动态库的加载。 和c 方法函数的绑定。使用lookup 方法 查询c 代码的函数指针。
这样就实现了, dart 代码 c 代码的直接调用
import 'dart:convert';
import 'dart:ffi';
import 'package:ffi/ffi.dart';
final DynamicLibrary dl = Platform.isAndroid
? DynamicLibrary.open('libfairflutter.so')
: DynamicLibrary.open('FairDynamicFlutter.framework/FairDynamicFlutter');
class FairMessageChannel {
Pointer<Utf8> Function(Pointer<Utf8>) invokeJSCommonFuncSync = dl
.lookup<NativeFunction<Pointer<Utf8> Function(Pointer<Utf8>)>>(
'invokeJSCommonFuncSync')
.asFunction();
dynamic sendCommonMessageSync(dynamic msg) =>
FairUtf8.fromUtf8(invokeJSCommonFuncSync.call(FairUtf8.toUtf8(msg)));
}
网友评论