2014-11-25 60 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。