Flutter FFI 学习笔记系列
- 《Flutter FFI 最简示例》
- 《Flutter FFI 基础数据类型》
- 《Flutter FFI 函数》
- 《Flutter FFI 字符串》
- 《Flutter FFI 结构体》
- 《Flutter FFI 类》
- 《Flutter FFI 数组》
- 《Flutter FFI 内存管理》
- 《Flutter FFI Dart Native API》
Dart 的数据类型与 C 的数据类型不一样,这就需要了解他们之间的对应关系。
1、NativeType
NativeType
是 Dart 中定义的抽象类,用于表示一种 Native
类型,它无法在 Dart 中进行构造,只能通过 FFI 接口返回。其定义如下:
/// [NativeType]'s subtypes represent a native type in C.
///
/// [NativeType]'s subtypes are not constructible in the Dart code and serve
/// purely as markers in type signatures.
abstract class NativeType {
const NativeType();
}
NativeType
是一种抽象类型,它有非常多的子类来表示 C 语言中的不同数据类型,如下:
2、C语言数据类型在 Dart 的表示形式
C 语言的数据类型在 Dart 中的表示形式如下表所示:
Dart 中定义的NativeType | C语言中的类型 | 说明 |
---|---|---|
Pointer | * | 指针类型 |
nullptr | NULL | 空指针 |
Void | void | void类型 |
NativeFunction | 函数 | 函数类型 |
Struct | struct | 结构体类型 |
Int8 | int8_t 或 char | 有符号8位整数 |
Uint8 | uint8_t 或 unsigned char | 无符号8位整数 |
Int16 | int16_t 或 short | 有符号16位整数 |
Uint16 | uint16_t 或 unsigned short | 无符号16位整数 |
Int32 | int32_t 或 int | 有符号32位整数 |
Uint32 | int32_t 或 unsigned int | 无符号32位整数 |
Int64 | int64_t 或 long long | 有符号64位整数 |
Uint64 | uint64_t 或 unsigned long long | 无符号64位整数 |
IntPtr | int* | 整数类型指针 |
Float | float | 单精度浮点类型 |
Double | double | 双精度浮点类型 |
Handle | Dart_Handle | Dart句柄在C中的表示形式 |
Opaque | opaque | 不透明类型,即不暴露其成员。一般用于表示C++中的类 |
dynamic | Dart_CObject | Dart对象在C中的表现形式 |
3、示例
下面是代码演示了如何在 Dart 中读取和改写 C 中的基本数据类型:
C代码:
#include <stdint.h>
#define DART_API extern "C" __attribute__((visibility("default"))) __attribute__((used))
DART_API int8_t int8 = -108;
DART_API uint8_t uint8 = 208;
DART_API int16_t int16 = -10016;
DART_API uint16_t uint16 = 20016;
DART_API int32_t int32 = -10032;
DART_API uint32_t uint32 = 20032;
DART_API int64_t int64 = -1000064;
DART_API uint64_t uint64 = 2000064;
DART_API float float32 = 3.1415;
DART_API double double64 = 2.17284949;
Dart 代码:
DynamicLibrary nativeAddLib = Platform.isAndroid
? DynamicLibrary.open("libnative_ffi.so")
: DynamicLibrary.process();
//变量映射
Pointer<Int8> int8 = nativeApi.lookup<Int8>("int8");
Pointer<Uint8> uint8 = nativeApi.lookup<Uint8>("uint8");
Pointer<Int16> int16 = nativeApi.lookup<Int16>("int16");
Pointer<Uint16> uint16 = nativeApi.lookup<Uint16>("uint16");
Pointer<Int32> int32 = nativeApi.lookup<Int32>("int32");
Pointer<Uint32> uint32 = nativeApi.lookup<Uint32>("uint32");
Pointer<Int64> int64 = nativeApi.lookup<Int64>("int64");
Pointer<Uint64> uint64 = nativeApi.lookup<Uint64>("uint64");
Pointer<Float> float32 = nativeApi.lookup<Float>("float32");
Pointer<Double> double64 = nativeApi.lookup<Double>("double64");
//变量值的读取
print("int8=${int8.value}");
print("uint8=${uint8.value}");
print("int16=${int16.value}");
print("uint16=${uint16.value}");
print("int32=${int32.value}");
print("uint32=${uint32.value}");
print("int64=${int64.value}");
print("uint64=${uint64.value}");
print("float32=${float32.value}");
print("double64=${double64.value}");
//变量值的改写
int8.value = 12;
uint8.value = 24;
print("int8=${int8.value}");
print("uint8=${uint8.value}");
//输出结果:
//I/flutter ( 2076): int8=12
//I/flutter ( 2076): uint8=64
//I/flutter ( 2076): int16=25472
//I/flutter ( 2076): uint16=14528
//I/flutter ( 2076): int32=-40128
//I/flutter ( 2076): uint32=80128
//I/flutter ( 2076): int64=-4000256
//I/flutter ( 2076): uint64=8000256
//I/flutter ( 2076): float32=12.565999984741211
//I/flutter ( 2076): double64=8.69139796
//I/flutter ( 2076): int8=12
//I/flutter ( 2076): uint8=24
说明:
lookup()
返回的是Pointer<T extends NativeType>
类型,是一个指针类型;- 通过
Pointer.value
属性可以获取和改写指针所指向的内存的值; - 通过
Pointer.address
属性可以获取指针的地址;
4、总结
上面介绍了基础数据类型(int
、float
等)的映射,其它类型(如:函数类型、结构体等)将在后面的章节中介绍,欢迎关注。