web-dev-qa-db-fra.com

Conversion de python objet chaîne en c char * à l'aide de ctypes

J'essaie d'envoyer 2 chaînes de Python (3.2) à C à l'aide de ctypes. Ceci est une petite partie de mon projet sur mon Raspberry Pi. Pour tester si la fonction C a reçu les chaînes correctement, J'en place un dans un fichier texte.

code Python

string1 = "my string 1"
string2 = "my string 2"

# create byte objects from the strings
b_string1 = string1.encode('utf-8')
b_string2 = string2.encode('utf-8')

# send strings to c function
my_c_function(ctypes.create_string_buffer(b_string1),
              ctypes.create_string_buffer(b_string2))

code C

void my_c_function(const char* str1, const char* str2)
{
    // Test if string is correct
    FILE *fp = fopen("//home//pi//Desktop//out.txt", "w");
    if (fp != NULL)
    {
        fputs(str1, fp);
        fclose(fp);
    }

    // Do something with strings..
}

Le problème

Seule la première lettre de la chaîne apparaît dans le fichier texte.

J'ai essayé de nombreuses façons de convertir l'objet chaîne Python avec des ctypes.

  • ctypes.c_char_p
  • ctypes.c_wchar_p
  • ctypes.create_string_buffer

Avec ces conversions, je reçois toujours l'erreur "mauvais type" ou "octets ou adresse entière attendus au lieu de l'instance str".

J'espère que quelqu'un pourra me dire où ça va mal. Merci d'avance.

19
LittleOne

Grâce à Eryksun la solution:

code Python

string1 = "my string 1"
string2 = "my string 2"

# create byte objects from the strings
b_string1 = string1.encode('utf-8')
b_string2 = string2.encode('utf-8')

# send strings to c function
my_c_function.argtypes = [ctypes.c_char_p, ctypes_char_p]
my_c_function(b_string1, b_string2)
21
LittleOne

Je pense que vous avez juste besoin d'utiliser c_char_p () au lieu de create_string_buffer ().

string1 = "my string 1"
string2 = "my string 2"

# create byte objects from the strings
b_string1 = string1.encode('utf-8')
b_string2 = string2.encode('utf-8')

# send strings to c function
my_c_function(ctypes.c_char_p(b_string1),
              ctypes.c_char_p(b_string2))

Si vous avez besoin de chaînes mutables, utilisez create_string_buffer () et convertissez-les en c_char_p à l'aide de ctypes.cast ().

11
Aksel

Avez-vous envisagé d'utiliser SWIG ? Je ne l'ai pas essayé moi-même mais voici à quoi cela ressemblerait, sans changer votre source C:

/*mymodule.i*/

%module mymodule
extern void my_c_function(const char* str1, const char* str2);

Cela rendrait votre Python aussi simple que (sauter la compilation):

import mymodule

string1 = "my string 1"
string2 = "my string 2"
my_c_function(string1, string2)

Remarque: je ne suis pas certain que .encode('utf-8') soit nécessaire si votre fichier source est déjà UTF-8.

1
user4113344