刚开始研究dart调用C、C++,走了很多弯路,以为char*和String转化必须通过自己写的Pointer来进行转换,熟不知,有更好的方法,flutter pub的ffi库封装了dart与C交互的所有方法,包括指针管理malloc、free等方法,以下简单说明。
参考链接
https://pub.flutter-io.cn/packages/ffi
https://github.com/dart-lang/sdk/tree/master/samples/ffi
在pubspec.yaml文件中添加
dependencies:
ffi: ^0.1.3
然后import ‘package:ffi/ffi.dart’;即可
import 'dart:core';
import 'dart:ffi';
import 'package:ffi/ffi.dart';
import "dart:convert";
import 'dart:io'; // For Platform.isX
final DynamicLibrary dylib = Platform.isAndroid
? DynamicLibrary.open("libnative_add.so")
: DynamicLibrary.open("native_add.framework/native_add");
// C string parameter pointer function - char *reverse(char *str, int length);
typedef reverse_func = Pointer<Utf8> Function(Pointer<Utf8> str, Int32 length);
typedef Reverse = Pointer<Utf8> Function(Pointer<Utf8> str, int length);
final reversePointer = dylib.lookup<NativeFunction<reverse_func>>('reverse');
final reverse = reversePointer.asFunction<Reverse>();
// C string pointer return function - char *hello_world();
// There's no need for two typedefs here, as both the
// C and Dart functions have the same signature
typedef hello_world_func = Pointer<Utf8> Function();
final helloWorldPointer =
dylib.lookup<NativeFunction<hello_world_func>>('hello_world');
final hello_world = helloWorldPointer.asFunction<hello_world_func>();
// changeString
final void Function(Pointer<Utf8>) changeString = dylib
.lookup<NativeFunction<Void Function(Pointer<Utf8>)>>("changeString")
.asFunction();
// C string parameter pointer function - char * testCallBack(callback cb)
typedef callback = Void Function(Pointer<Utf8>);//注意void 和Void的区别
typedef testCallBack_func = Int32 Function(Pointer<NativeFunction<callback>> func);
typedef TestStringCallBack = int Function(Pointer<NativeFunction<callback>> func);
final testCallBackPointer = dylib.lookup<NativeFunction<testCallBack_func>>('testStringCallBack');
final testStringCallBack = testCallBackPointer.asFunction<TestStringCallBack>();
void testStrinfCb(Pointer<Utf8> str)
{
print('${Utf8.fromUtf8(str)}');
// free(str);
print('cb end');
}
Pointer<NativeFunction<callback>> pFunc = Pointer.fromFunction(testStrinfCb);
main()
{
print('start main');
{
// Basic operation: allocate, get, set, and free.
Pointer<Int64> p = allocate();
p.value = 42;
int pValue = p.value;
print('${p.runtimeType} value: ${pValue}');
free(p);
}
{
// Undefined behavior before set.
Pointer<Int64> p = allocate();
int pValue = p.value;
print('If not set, returns garbage: ${pValue}');
free(p);
}
{
// Allocate and free some native memory with malloc and free.
final pointer = allocate<Uint8>();
pointer.value = 3;
print(pointer.value);
free(pointer);
print(pointer.value);
// Use the Utf8 helper to encode null-terminated Utf8 strings in native memory.
final String myString = "😎👿💬";
final Pointer<Utf8> charPointer = Utf8.toUtf8(myString);
print("First byte is: ${charPointer.cast<Uint8>().value}");
print(Utf8.fromUtf8(charPointer));
print('free before:: ${Utf8.fromUtf8(charPointer)}');
free(charPointer);
print('free after:: ${Utf8.fromUtf8(charPointer)}');
}
{
final String str = "hello world 123456";
final charpoint = reverse(Utf8.toUtf8(str),str.length);
print('reverse ${Utf8.fromUtf8(charpoint)}');
free(charpoint);
}
{
final String str = "hello world 123456";
Pointer<Utf8> charPoint = Utf8.toUtf8(str);
print('changeString:: ${charPoint.address} ${Utf8.fromUtf8(charPoint)}');
changeString(charPoint);
print('changeString:: ${charPoint.address} ${Utf8.fromUtf8(charPoint)}');
free(charPoint);// is ok
//print('changeString:: ${charPoint.address} ${Utf8.fromUtf8(charPoint)}');
}
{
Pointer<Utf8> p1 = hello_world();
print('hello_world: ${Utf8.fromUtf8(p1)}');
free(p1);
print('hello_world: ${Utf8.fromUtf8(p1)}');
}
//test callback
{
testStringCallBack(pFunc);
}
}