DART 调用 C代码,指针,回调等

1、参考牛人 侍风念影 博客 https://www.cnblogs.com/caijinglong/p/11793119.html,完成基本的项目搭建、函数调用

以下dart版本信息为
在这里插入图片描述

2、Dart调用C函数传参是指针的函数:

C代码

 //在C函数内分配空间
  int *creatpoint(int size)
    {
        int *mult = (int *)malloc(size*sizeof(int));
        return mult;
    }
 //传参为指针的C函数
    int subtract(int *a, int b)
    {
        return *a - b;
    }

DART 代码

函数签名
final Pointer Function(int a) creatpoint = dylib
    .lookup Function(Int32 a)>>("creatpoint")
    .asFunction();
typedef subtract_func = Int32 Function(Pointer a, Int32 b);
typedef Subtract = int Function(Pointer a, int b);
  final subtractPointer =
      dylib.lookup>('subtract');
  final subtract = subtractPointer.asFunction();
  
  函数调用
  Pointer pp = creatpoint(5);
	pp.value = 10;
	print("testPointInt32 ---------------${subtract(pp,2)}");

3 char*和DART 字符串String转换

利用Pointer完成char和String的转换;
在C函数中传参或者返回值为char
的函数,在导入的函数签名里面,把char*传参写成Pointer,然后利用下面String CStringtoString(Pointer str) 方法,把Pointer转化为String

  /// 将c语言中的字符串转为dart中的字符串
 String CStringtoString(Pointer str) 
 {
   if (str == null)
   {
       return null;
   } 
   int len = 0;
   while (str.elementAt(++len).value != 0);
   List units = List(len);
   for (int i = 0; i < len; ++i)
    units[i] = str.elementAt(i).value;
    return Utf8Codec().decode(units);
 }

同理,dart的String转为char*,把String转为Pointer即可;
// 申请内存空间,将dart字符串转为c语言字符串

	Pointer  stringToCString(String dartstr)
	{
	      List units = Utf8Codec().encode(dartstr);
	      Pointer str = creatCharPoint(units.length + 1);
	      for (int i = 0; i < units.length; ++i)
	       {
	        str.elementAt(i).value = units[i];
	      }
	      str.elementAt(units.length).value = 0;
	      return str.cast();
	  }

以下为例子

C代码

   char * creatCharPoint(int size)
{
    char *mult = (char *)malloc(size*sizeof(char));
    return mult;
}

  char *hello_world()
    {
        return "Hello World";
    }

char *reverse(char *str, int length)
{
    char *reversed_str = (char *)malloc((length + 1) * sizeof(char));
    for (int i = 0; i < length; i++)
    {
        reversed_str[length - i - 1] = str[i];
    }
    reversed_str[length] = '\0';
    return reversed_str;
}

DART 代码

//分配空间 a *sizeof(char *)大小的内存
final Pointer Function(int a) creatCharPoint = dylib
.lookup Function(Int32 a)>>("creatCharPoint")
.asFunction();

 // 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 Function();
  final helloWorldPointer =
      dylib.lookup>('hello_world');
  final hello_world = helloWorldPointer.asFunction();

  // C string parameter pointer function - char *reverse(char *str, int length);
typedef reverse_func = Pointer Function(Pointer str, Int32 length);
typedef Reverse = Pointer Function(Pointer str, int length);
final reversePointer = dylib.lookup>('reverse');
final reverse = reversePointer.asFunction();

final messagePointer = hello_world();
String message = CStringtoString(messagePointer);
print('${messagePointer}------creat point $message');

 Pointer str1 = stringToCString('hello world');
Pointer str2 = reverse(str1, 11);
String reversedMessage = CStringtoString(str2);
print('$reversedMessage');

4 回调

通过将函数指针转化为Pointer来进行函数的传参

C代码

typedef void(*callback)();
 static int g_jCount = 0;
    int testCallBack(callback cb)
{
    for(int i = 0;i< 2;i++)
    {
        cb();
        g_jCount++;
    }
    return g_jCount;
}

DART 代码

 // C string parameter pointer function -  char * testCallBack(callback cb)
typedef callback = Void Function();//注意void 和Void的区别
typedef testCallBack_func = Int32 Function(Pointer>  func);
typedef TestCallBack = int Function(Pointer>  func);
final testCallBackPointer = dylib.lookup>('testCallBack');
final testCallBack = testCallBackPointer.asFunction();

 int count = 0;
void dartCallback()
{
    count = count + 1;
    print('dart callback,${count}');
}
Pointer> pFunc = Pointer.fromFunction(dartCallback);
print('pFunc =============== ${testCallBack(pFunc)}');

5 dart调用自己写的so库

在Andriod/app 下的build.gradle文件中添加
android {
sourceSets {
main.jniLibs.srcDir “${project.projectDir.path}/…/…/lib”
}
}
然后在根目录lib文件夹下穿件对应平台的文件夹,比如x86,把libuntitled.so文件放到此目录下

final DynamicLibrary exlib = Platform.isAndroid
    ? DynamicLibrary.open('libuntitled.so')
    : DynamicLibrary.open("native_add.framework/native_add");
	
final int Function(int x, int y) testadd = exlib
    .lookup>("testadd")
    .asFunction();

print('test2 testadd(10,50)=============== ${testadd(10,50)}');
I/flutter (22014): test2 testadd(10,50)=============== 60

参考资料

https://www.cnblogs.com/caijinglong/p/11793119.html

https://flutter.dev/docs/development/platform-integration/c-interop

https://github.com/dart-lang/sdk/blob/e5705943d8cc21fb0ef592fdf8162fcf81ee2472/samples/ffi/sample_ffi_functions_callbacks.dart

https://github.com/dart-lang/samples/blob/8ce5e8b671689b2a415f38ea17fc239a599d0a09/ffi/primitives/primitives.dart

https://github.com/dart-lang/sdk/tree/master/samples/ffi

你可能感兴趣的:(Dart与C)