[LINUX] Appelez la fonction C avec dart: ffi et rappelez la fonction Dart

introduction

Vous trouverez des instructions sur l'utilisation de dart: ffi pour appeler des fonctions C depuis Dart sur la page suivante.

Cependant, tous étaient des exemples d'appels de fonction de synchronisation simples, donc J'écrirai comment implémenter l'appel de la fonction de rappel comme rappel. Si vous avez des erreurs ou de meilleurs moyens, veuillez nous en informer

Aucune documentation n'a été trouvée, Exemple Dans dart-lang / sdk. dev / samples / ffi / sample_ffi_functions_callbacks.dart) a été trouvé, alors j'y ai fait référence.

L'environnement de vérification de fonctionnement est le suivant. De plus, nous avons confirmé le fonctionnement sur Linux Desktop en tant que plate-forme de 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)

Fonction de rappel à implémenter cette fois

Cette fois, j'ai choisi qsort (3) comme fonction pour appeler la fameuse fonction de rappel qui peut être utilisée n'importe où. En fait, je pense que j'utiliserai qsort_r (3), mais comme ce n'est pas le point principal de cette fois, j'utilise qsort (3) pour garder le code simple.

Voici un prototype et une description de qsort (3) de man.

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

[man qsort(3)] La fonction qsort () trie un tableau avec des éléments de taille nmemb size. L'argument de base est un pointeur vers le début du tableau. La fonction de comparaison par point de comparaison organise le contenu du tableau dans l'ordre croissant (plus la valeur est élevée, plus tard). L'argument de la fonction de comparaison est un pointeur vers les deux objets comparés.

La fonction de comparaison est 1) inférieure à zéro, 2) zéro, 3) inférieure à zéro, selon que le premier argument est 1) inférieur, 2) égal ou 3) supérieur au deuxième argument. Doit retourner l'un des plus grands entiers. Lorsque les résultats de comparaison des deux éléments sont égaux, l'ordre des deux n'est pas spécifié dans la séquence réorganisée.

Utilisez ce qsort (3) pour trier le tableau int par ordre croissant. S'il est implémenté en langage C, c'est comme suit.

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

//fonction de rappel
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;
}

Cette fois, le même processus est appelé via dart: ffi.

Appeler qsort (3) depuis Dart

Maintenant, je publierai immédiatement l'implémentation dans Dart.

//Définition du type
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>>);

//fonction de rappel
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) {
  //Convertir la liste de fléchettes en tableau C
  final dataPtr = intListToArray(data);

  // qsort(3)Obtenez le gestionnaire de la libc qui définit
  final libc = DynamicLibrary.open('libc.so.6');

  //Récupérez l'adresse du symbole qsort depuis la libc et convertissez-la en fonction Dart
  final qsort =
      libc.lookup<NativeFunction<NativeQsort>>('qsort').asFunction<Qsort>();

  //Convertir la fonction Dart par rapport au pointeur de fonction C
  Pointer<NativeFunction<NativeCompar>> pointer =
      Pointer.fromFunction(compar, 0);

  //libc qsort(3)Appelé en passant le tableau, le nombre d'éléments, la taille de l'élément et le pointeur de fonction à
  qsort(dataPtr, data.length, sizeOf<Int32>(), pointer);

  //Convertir un tableau C en liste de fléchettes
  return arrayToIntList(dataPtr, data.length);
}

Le flux de traitement est décrit sous forme de commentaire.

Le point lors du passage de la fonction Dart en tant que fonction de rappel est Pointer # fromFunction. .. Vous pouvez convertir une fonction Dart en un pointeur de fonction C avec cette méthode. Quant aux arguments, ceux qui sont évidents seront automatiquement rassemblés.

Le code qui fonctionne comme l'application Flutter dans l'exemple ci-dessus est ci-dessous.

en conclusion

D'autres liaisons de langage ont beaucoup de conversions de type et sont forcément longues en notation Si vous le lisez calmement, c'est essentiellement la même chose que la gestion des pointeurs de fonction en langage C.

Bien sûr, lors de son utilisation réelle en développement, gestion des erreurs, gestion des ressources, prévention des erreurs typographiques subtiles, Ingéniosité pour réduire le nombre de copies, mise en cache des gestionnaires de bibliothèques et des symboles, etc. Il y a beaucoup d'autres choses à penser, Si vous n'êtes pas confus par la conversion de type, je pense que vous pouvez y penser de la même manière que le développement natif.

référence

Recommended Posts

Appelez la fonction C avec dart: ffi et rappelez la fonction Dart
Appelez l'API avec python3.
Qu'est-ce que la fonction de rappel?
Appeler C depuis Python avec DragonFFI
Pointeur de fonction et objdump ~ Langage C ~
Graphique d'appel de sortie avec PyCallGraph
Code-Server x Dart avec ffi x Go x Clang
RaspberryPi L Chika avec Python et C #
[Langage C] Faites attention à la combinaison de l'API de mise en mémoire tampon et de l'appel système sans mise en mémoire tampon
Gratter l'holojour et l'afficher dans la CLI
J'ai essayé la synthèse de fonctions et le curry avec python
Résolution du modèle Lorenz 96 avec Julia et Python
Archivez et compressez tout le répertoire avec python
Décrivez ec2 avec boto3 et récupérez la valeur
Dans Python3.8 et versions ultérieures, le mod inverse peut être calculé avec la fonction intégrée pow.