How to use dart: ffi that calls C function from Dart is documented on the following page.
However, all of them were examples of simple synchronization function calls, so I will write the implementation method of the callback function call as a reminder. If you have any mistakes or better ways, please let us know.
The document was not found, Sample in dart-lang / sdk. dev / samples / ffi / sample_ffi_functions_callbacks.dart) was found, so I referred to it.
The operation check environment is as follows. In addition, we have confirmed the operation on Linux Desktop as the platform of Flutter.
$ uname -a
Linux chama 5.5.8 #1 SMP Sat Mar 7 22:29:22 JST 2020 x86_64 x86_64 x86_64 GNU/Linux
$ lsb_release -d
Description: Ubuntu 18.04.5 LTS
$ flutter --version
Flutter 1.24.0-8.0.pre.117 • channel master • https://github.com/flutter/flutter
Framework • revision 8cb2665118 (8 hours ago) • 2020-11-06 16:02:19 +0800
Engine • revision 0693ee04d1
Tools • Dart 2.12.0 (build 2.12.0-21.0.dev)
This time I chose qsort (3)
as a function to call the famous callback function that can be used anywhere.
Actually, I think I will use qsort_r (3)
, but since it is not the main point of this time, I use qsort (3)
to keep the code simple.
Here is a prototype and description of qsort (3)
from man.
void qsort(void *base, size_t nmemb, size_t size,
int (*compar)(const void *, const void *));
[man qsort(3)] The qsort () function sorts an array with nmemb size size elements. The base argument is a pointer to the beginning of the array. The compar-pointed comparison function sorts the contents of the array in ascending order (the higher the value, the later). The argument of the comparison function is a pointer to the two objects being compared.
The comparison function is 1) an integer less than zero, 2) zero, 3) less than zero, depending on whether the first argument is 1) less, 2) equal, or 3) greater than the second argument. Must return one of the larger integers. When the comparison results of the two elements are equal, the order of the two is not specified in the rearranged array.
Use this qsort (3)
to sort an array of ints in ascending order.
If implemented in C language, it is as follows.
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
//callback function
static int compar(const void* rhs_ptr, const void* lhs_ptr) {
int32_t rhs = *(int32_t*)rhs_ptr;
int32_t lhs = *(int32_t*)lhs_ptr;
if (rhs > lhs) {
return 1;
} else if (rhs < lhs) {
return -1;
} else {
return 0;
}
}
int main(void) {
int32_t array[] = {1, 5, -10, 3, 9, 8, 7, 13};
qsort(array, sizeof(array) / sizeof(array[0]), sizeof(array[0]), compar);
for (uint32_t i = 0; i < sizeof(array) / sizeof(array[0]); i++) {
printf("%d\n", array[i]);
}
return 0;
}
This time we call the same process via dart: ffi.
qsort (3)
from DartNow, I will post the implementation in Dart immediately.
//Type definition
typedef NativeCompar = Int32 Function(Pointer<Int32>, Pointer<Int32>);
typedef NativeQsort = Void Function(
Pointer<Int32>, Uint64, Uint64, Pointer<NativeFunction<NativeCompar>>);
typedef Qsort = void Function(
Pointer<Int32>, int, int, Pointer<NativeFunction<NativeCompar>>);
//callback function
int compar(Pointer<Int32> rhsPtr, Pointer<Int32> lhsPtr) {
final rhs = rhsPtr.value;
final lhs = lhsPtr.value;
if (rhs > lhs) {
return 1;
} else if (rhs < lhs) {
return -1;
} else {
return 0;
}
}
List<int> qsort(final List<int> data, _compar) {
//Convert Dart List to C array
final dataPtr = intListToArray(data);
// qsort(3)Get the handler for libc that defines
final libc = DynamicLibrary.open('libc.so.6');
//Get the address of the symbol qsort from libc and convert it to the Dart function
final qsort =
libc.lookup<NativeFunction<NativeQsort>>('qsort').asFunction<Qsort>();
//Convert Dart function compar to C function pointer
Pointer<NativeFunction<NativeCompar>> pointer =
Pointer.fromFunction(compar, 0);
//libc qsort(3)Called by passing an array, number of elements, element size, function pointer to
qsort(dataPtr, data.length, sizeOf<Int32>(), pointer);
//Convert an array of C to a List of Dart
return arrayToIntList(dataPtr, data.length);
}
The processing flow is described as a comment.
The point when passing the Dart function as a callback function is Pointer # fromFunction .. You can use this method to convert a Dart function to a C function pointer. As for the arguments, those that are obvious will be marshalled automatically.
The code that works as the above sample Flutter app is below.
Other language bindings have a lot of type conversions and are inevitably long in notation, If you read it calmly, it is essentially the same as handling function pointers in C language.
Of course, when actually using it in development, error handling, resource management, prevention of subtle type mistakes, Ingenuity to reduce the number of copies, caching of library handlers and symbols, etc. There are many other things to think about, If you are not confused by type conversion, I think that you can think of it in the same way as Native development.
sdk/sample_ffi_functions_callbacks.dart at 2.12.0-21.0.dev · dart-lang/sdk --Sample making callback call with dart: ffi in dart-lang / sdk --The code on the native side is ffi_test_functions on the runtime side
samples/ffi at master · dart-lang/samples --ffi samples from dart-lang / samples
ffi_tool | Dart Package --Package for automatically generating code for ffi calls
-FFI in Flutter --There is no mention of callbacks, but it was very helpful for me to summarize the history of FFI in an easy-to-understand manner.
Recommended Posts