2014-11-25 2 views
10

Я пытаюсь отправить 2 строки из Python (3.2) в C, используя ctypes. Это небольшая часть моего проекта на моей малиновой пи. Чтобы проверить, правильно ли выполнялась функция C, я помещаю один из них в текстовый файл.Преобразование строкового объекта python в c char * с использованием ctypes

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

код 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.. 
} 

Проблема

Только первая буква строки появится в текстовом файле.

Я пробовал много способов конвертировать строковый объект Python с ctypes.

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

С помощью этих преобразований я получаю ошибку "неверный тип" или «байт или целое адрес ожидается вместо экземпляра ул ».

Надеюсь, кто-то скажет мне, где это происходит. Спасибо заранее.

+6

Установите 'my_c_function.argtypes = [ctypes.c_char_p, ctypes.c_char_p]'. Затем, поскольку параметры 'const', просто назовите его как' my_c_function (b_string1, b_string2) '. – eryksun

+2

FYI, буквальный символ обратной косой черты должен быть экранирован как '' \\ "', но это не требуется для косой черты. Это просто '' /home/pi/Desktop/out.txt''. – eryksun

+1

@eryksun Спасибо за ваш ответ. Теперь он работает, я совершенно забыл, что у меня были argtypes, все еще установленные на c_wchar_p. Что касается косых черт, я всегда их смешиваю. – LittleOne

ответ

10

Благодаря Eryksun решение:

код 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) 
1

Рассматривали ли вы с помощью SWIG? Я не пробовал сам, но вот то, что это будет выглядеть, не меняя источник C:

/*mymodule.i*/ 

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

Это сделает ваш источник Python так просто, как (пропуск компиляции):

import mymodule 

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

Примечание Я не уверен, что .encode('utf-8') необходим, если ваш исходный файл уже UTF-8.

+2

Для Python 3 не забудьте использовать параметр '-py3' swig. Оболочка кодирует строку Python 3 как UTF-8, используя ['PyUnicode_AsUTF8String'] (https://docs.python.org/3/c-api/unicode.html#c.PyUnicode_AsUTF8String), а затем [' PyBytes_AsStringAndSize'] (https://docs.python.org/3/c-api/bytes.html#c.PyBytes_AsStringAndSize). Передача 'bytes' вызывает' TypeError'. – eryksun

4

Я думаю, вам просто нужно использовать c_char_p() вместо 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)) 

Если вам нужны изменяемые строки используйте create_string_buffer() и отбрасывать те c_char_p с помощью ctypes.cast().

Смежные вопросы