2014-11-25 58 views
10

我想從Python(3.2)向使用ctypes的C發送2個字符串。這是我的Raspberry Pi項目中的一小部分。爲了測試C函數是否正確接收了字符串,我將其中的一個放置在文本文件中。使用ctypes將python字符串對象轉換爲c char *

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

有了這些轉換我不斷收到錯誤 「錯誤類型」 或「預期而不是STR例如字節或整數地址」。

我希望有人能告訴我哪裏出問題了。 在此先感謝。

+6

設置'my_c_function.argtypes = [ctypes.c_char_p,ctypes.c_char_p]'。然後,因爲參數是'const',所以簡單地稱之爲'my_c_function(b_string1,b_string2)'。 – eryksun 2014-11-25 14:38:06

+2

僅供參考,一個文字反斜線字符需要轉義爲'「\\」',但它不是正斜槓所必需的。它只是'「/home/pi/Desktop/out.txt」'。 – eryksun 2014-11-25 14:42:35

+1

@eryksun感謝您的回覆。它現在起作用了,我完全忘記了我的argtypes仍然設置在c_wchar_p上。關於斜槓,我總是讓它們混淆起來。 – LittleOne 2014-11-25 15:03:12

回答

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) 

注如果您的源文件已經是UTF-8,我不確定.encode('utf-8')是否必要。

+2

對於Python 3請記住使用swig的'-py3'選項。包裝器使用['PyUnicode_AsUTF8String'](https://docs.python.org/3/c-api/unicode.html#c.PyUnicode_AsUTF8String),然後['PyBytes_AsStringAndSize']將一個Python 3字符串編碼爲UTF-8。 (https://docs.python.org/3/c-api/bytes.html#c.PyBytes_AsStringAndSize)。傳遞'bytes'會引發一個'TypeError'。 – eryksun 2014-11-25 18:21:17

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()並使用ctypes.cast()將其轉換爲c_char_p。