[LINUX] Rufen Sie die C-Funktion mit dart: ffi auf und rufen Sie die Dart-Funktion zurück

Einführung

Anweisungen zur Verwendung von dart: ffi zum Aufrufen von C-Funktionen von Dart finden Sie auf der folgenden Seite.

Alle waren jedoch Beispiele für einfache Synchronisationsfunktionsaufrufe Ich werde als Erinnerung aufschreiben, wie der Rückruffunktionsaufruf implementiert wird. Wenn Sie Fehler oder bessere Möglichkeiten haben, lassen Sie es uns bitte wissen.

Es wurde keine Dokumentation gefunden. In dart-lang / sdk [Beispiel](https://github.com/dart-lang/sdk/blob/2.12.0-21.0. dev / samples / ffi / sample_ffi_functions_callbacks.dart) wurde gefunden, also habe ich darauf verwiesen.

Die Betriebsüberprüfungsumgebung ist wie folgt. Darüber hinaus haben wir den Betrieb auf Linux Desktop als Plattform von Flutter bestätigt.

$ 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)

Rückruffunktion, die diesmal implementiert werden soll

Dieses Mal habe ich "qsort (3)" als Funktion gewählt, um die berühmte Rückruffunktion aufzurufen, die überall verwendet werden kann. Eigentlich denke ich, dass ich "qsort_r (3)" verwenden werde, aber da dies nicht der Hauptpunkt dieser Zeit ist, verwende ich "qsort (3)", um den Code einfach zu halten.

Hier ist ein Prototyp und eine Beschreibung von "qsort (3)" von man.

void qsort(void *base, size_t nmemb, size_t size,
           int (*compar)(const void *, const void *));

[man qsort(3)] Die Funktion qsort () sortiert ein Array mit Elementen der Größe nmemb. Das Basisargument ist ein Zeiger auf den Anfang des Arrays. Die vergleichende Vergleichsfunktion ordnet den Inhalt des Arrays in aufsteigender Reihenfolge an (je höher der Wert, desto später). Das Argument der Vergleichsfunktion ist ein Zeiger auf die beiden zu vergleichenden Objekte.

Die Vergleichsfunktion ist 1) kleiner als Null, 2) Null, 3) kleiner als Null, je nachdem, ob das erste Argument 1) kleiner, 2) gleich oder 3) größer als das zweite Argument ist. Muss eine der größeren ganzen Zahlen zurückgeben. Wenn die Vergleichsergebnisse der beiden Elemente gleich sind, wird die Reihenfolge der beiden in der neu angeordneten Reihenfolge nicht angegeben.

Verwenden Sie dieses qsort (3), um das int-Array in aufsteigender Reihenfolge zu sortieren. Wenn in C-Sprache implementiert, ist es wie folgt.

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>

//Rückruffunktion
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;
}

Diesmal wird der gleiche Vorgang über dart: ffi aufgerufen.

Rufen Sie "qsort (3)" von Dart aus auf

Jetzt werde ich die Implementierung sofort in Dart veröffentlichen.

//Typdefinition
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>>);

//Rückruffunktion
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) {
  //Dartliste in C-Array konvertieren
  final dataPtr = intListToArray(data);

  // qsort(3)Holen Sie sich den Handler für libc, der definiert
  final libc = DynamicLibrary.open('libc.so.6');

  //Holen Sie sich die Adresse des Symbols qsort von libc und konvertieren Sie es in die Dart-Funktion
  final qsort =
      libc.lookup<NativeFunction<NativeQsort>>('qsort').asFunction<Qsort>();

  //Dart-Funktion im Vergleich zum C-Funktionszeiger konvertieren
  Pointer<NativeFunction<NativeCompar>> pointer =
      Pointer.fromFunction(compar, 0);

  //libc qsort(3)Wird aufgerufen, indem das Array, die Anzahl der Elemente, die Elementgröße und der Funktionszeiger an übergeben werden
  qsort(dataPtr, data.length, sizeOf<Int32>(), pointer);

  //Konvertieren Sie das C-Array in die Dart-Liste
  return arrayToIntList(dataPtr, data.length);
}

Der Verarbeitungsablauf wird als Kommentar beschrieben.

Der Punkt beim Übergeben der Dart-Funktion als Rückruffunktion ist Pointer # fromFunction. .. Mit dieser Methode können Sie eine Dart-Funktion in einen C-Funktionszeiger konvertieren. Wenn es offensichtlich ist, werden die Argumente automatisch gemarshallt.

Der Code, der im obigen Beispiel als Flutter-App fungiert, ist unten aufgeführt.

abschließend

Andere Sprachbindungen haben viele Typkonvertierungen und sind unweigerlich lang in der Notation. Wenn Sie es ruhig lesen, entspricht es im Wesentlichen dem Umgang mit Funktionszeigern in der Sprache C.

Natürlich, wenn es tatsächlich in der Entwicklung, Fehlerbehandlung, Ressourcenverwaltung, Vermeidung subtiler typografischer Fehler verwendet wird, Einfallsreichtum, um die Anzahl der Kopien zu reduzieren, Bibliothekshandler und Symbole zwischenzuspeichern usw. Es gibt viele andere Dinge, über die man nachdenken muss, Wenn Sie durch die Typkonvertierung nicht verwirrt sind, können Sie sich das genauso vorstellen wie die native Entwicklung.

Referenz

Recommended Posts

Rufen Sie die C-Funktion mit dart: ffi auf und rufen Sie die Dart-Funktion zurück
Rufen Sie die API mit python3 auf.
Was ist die Rückruffunktion?
Rufen Sie C von Python mit DragonFFI auf
Funktionszeiger und objdump ~ C language ~
Anrufdiagramm mit PyCallGraph ausgeben
Code-Server x Dart mit ffi x Go x Clang
RaspberryPi L Chika mit Python und C #
[C-Sprache] Achten Sie auf die Kombination aus Puffer-API und nicht pufferndem Systemaufruf
Schaben Sie den Holojour ab und zeigen Sie ihn in der CLI an
Ich habe Funktionssynthese und Curry mit Python versucht
Lösen des Lorenz 96-Modells mit Julia und Python
Archivieren und komprimieren Sie das gesamte Verzeichnis mit Python
Beschreibe ec2 mit boto3 und rufe den Wert ab
In Python3.8 und höher kann der inverse Mod mit der integrierten Funktion pow berechnet werden.