使用 ctypes 将 python 字符串对象转换为 c char*

Posted

技术标签:

【中文标题】使用 ctypes 将 python 字符串对象转换为 c char*【英文标题】:Converting python string object to c char* using ctypes 【发布时间】:2015-01-23 11:56:54 【问题描述】:

我正在尝试使用 ctypes 将 2 个字符串从 Python (3.2) 发送到 C。这是我的树莓派项目的一小部分。为了测试 C 函数是否正确接收字符串,我将其中一个放在文本文件中。

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

问题

只有字符串的第一个字母出现在文本文件中。

我尝试了很多方法来用 ctypes 转换 Python 字符串对象。

ctypes.c_char_p ctypes.c_wchar_p ctypes.create_string_buffer

通过这些转换,我不断收到错误“错误类型”或“预期的字节或整数地址而不是 str 实例”。

我希望有人能告诉我哪里出错了。 提前致谢。

【问题讨论】:

设置my_c_function.argtypes = [ctypes.c_char_p, ctypes.c_char_p]。然后,因为参数是const,所以直接调用为my_c_function(b_string1, b_string2) 仅供参考,文字反斜杠字符需要转义为"\\",但正斜杠不需要。只是"/home/pi/Desktop/out.txt" @eryksun 感谢您的回复。它现在可以工作了,我完全忘记了我还在 c_wchar_p 上设置了 argtypes。关于斜线,我总是把它们弄混。 只在函数修改字符串时使用buf = ctypes.create_string_buffer(bstr)。相当于buf = (ctypes.c_char * (len(bstr) + 1))();buf.value = bstr 【参考方案1】:

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

【讨论】:

my_c_function.argtypes = [ctypes.c_char_p, ctypes_char_p] 你的意思是my_c_function.argtypes = [ctypes.c_char_p, ctypes.char_p](注意. 而不是_)? 哈哈,5 年后有人注意到或觉得麻烦指出这一点。谢谢你,我在答案中编辑了它。 你知道,强迫症! my_c_function.argtypes = [ctypes.c_char_p, ctypes.char_p] 你的意思是my_c_function.argtypes = [ctypes.c_char_p, ctypes.c_char_p] 吗?【参考方案2】:

我认为你只需要使用 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。

【讨论】:

【参考方案3】:

您是否考虑过使用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') 是否必要。

【讨论】:

对于 Python 3,请记住使用 swig 的 -py3 选项。包装器将 Python 3 字符串编码为 UTF-8,使用PyUnicode_AsUTF8String,然后使用PyBytes_AsStringAndSize。传递bytes 会引发TypeError

以上是关于使用 ctypes 将 python 字符串对象转换为 c char*的主要内容,如果未能解决你的问题,请参考以下文章

Python - 将字符串对象转换为 ctypes (unsigned char *)

ctypes - 将 c++ 函数的输出转换为 python 对象

[转]python使用ctypes模块调用windowsapi获取系统版本

如何使用 ctypes 将此 Python 对象移动到 C++ 中?

将 multiprocessing.Value 对象传递给 ctype 函数?

如何使用ctypes,python将字符串参数传递给C++函数