Comment Python peut obtenir des données binarys (char *) à partir de C ++ par SWIG?

J’utilise des fonctions C ++ en Python par SWIG et j’ai rencontré un problème maintenant. Lorsque je passe un caractère * de C ++ à Python, le caractère * est tronqué par Python.

Par exemple:

exemple.h:

char * fun() { return "abc\0de"; } 

maintenant en Python, nous appelons example.fun (), il affiche seulement “abc” au lieu de “abc \ 0de”, les données derrière “\ 0” sont supprimées par Python.

Je veux obtenir tous les caractères (c’est une donnée binary pouvant contenir ‘\ 0’) de fun () en C ++, et tout conseil est apprécié

Les chaînes C / C ++ sont terminées par NULL, ce qui signifie que le premier caractère \0 désigne la fin de la chaîne.

Lorsqu’une fonction renvoie un pointeur sur une telle chaîne, l’appelant (SWIG dans ce cas) n’a aucun moyen de savoir s’il y a plus de données après le premier \0 , c’est pourquoi vous n’obtenez que la première partie.

La première chose à faire est donc de changer votre fonction C pour renvoyer non seulement la chaîne, mais aussi sa longueur. Comme il ne peut y avoir qu’une seule valeur de retour, nous allons utiliser des arguments de pointeur.

 void fun(char** s, int *sz) { *s = "abc\0de"; *sz = 6; } 

Les documents SWIG suggèrent d’utiliser la bibliothèque cssortingng.i pour envelopper de telles fonctions. En particulier, la dernière macro fait exactement ce dont vous avez besoin.

 %cssortingng_output_allocate_size(parm, szparm, release) 

Lisez la documentation pour apprendre à l’utiliser.

Tout d’abord, vous ne devriez pas utiliser char * si vous utilisez des données binarys (swig pense qu’il s’agit de chaînes normales). Au lieu de cela, vous devriez utiliser void * . swig fournit un module nommé ‘cdata.i’ – vous devez l’inclure dans le fichier de définition d’interface.

Une fois que vous avez inclus cela, cela donne deux fonctions – cdata() et memmove() .

  • Avec un void * et la longueur des données binarys, cdata() convertit en un type de chaîne de la langue cible.
  • memmove() effectue l’inverse – si un type de chaîne est utilisé, il en copiera le contenu (y compris les octets nuls incorporés) dans le type C void* .

La gestion des données binarys devient beaucoup plus simple avec ce module. J’espère que c’est ce dont vous avez besoin.

 example.i %module example %include "cdata.i" %{ void *fun() { return "abc\0de"; } %} test.py import example print example.cdata(example.fun(), 6) 

Voir 8.3 C Ssortingng Handling dans la documentation.

Aussi de la documentation :

Le type de données char * est traité comme une chaîne ASCII terminée par NULL. SWIG mappe cela en une chaîne de caractères de 8 bits dans le langage de script cible. SWIG convertit les chaînes de caractères du langage cible en chaînes terminées par NULL avant de les transmettre en C / C ++. Le traitement par défaut de ces chaînes ne leur permet pas d’avoir des octets NULL incorporés. Par conséquent, le type de données char * n’est généralement pas adapté à la transmission de données binarys. Cependant, il est possible de changer ce comportement en définissant un typemap SWIG. Voir le chapitre sur les typemaps pour plus de détails à ce sujet.