如何在Python 3 C API中从str类型PyObject*提取char*?
在Python 3 C API中从str类型PyObject提取char的解决方案
核心结论
Python 3中的str类型对应C API里的PyUnicodeObject,直接用Unicode相关API处理即可,无需转成bytes。
正确操作步骤
类型校验
用PyUnicode_Check(obj)判断传入的PyObject*是否为Python 3的str对象。如果你的代码里这个函数匹配不了str(...)创建的对象,大概率是D语言绑定的问题:- 确认链接的是Python 3的库而非Python 2
- 检查D语言对
PyUnicode_Check的绑定是否正确,有没有误映射到Python 2的旧API
*提取UTF-8编码的char **
Python 3的str是Unicode字符串,直接用以下API提取UTF-8格式的char*:PyUnicode_AsUTF8(obj):返回UTF-8编码的const char*,内存由Python管理,不要手动释放PyUnicode_AsUTF8AndSize(obj, &size):同时返回字符串指针和长度,同样无需手动释放内存
示例代码(C语言,D语言可参照调用逻辑)
#include <Python.h> void process_python_str(PyObject* str_obj) { if (!PyUnicode_Check(str_obj)) { PyErr_SetString(PyExc_TypeError, "必须传入str类型对象"); return; } // 提取字符串(不带长度) const char* utf8_content = PyUnicode_AsUTF8(str_obj); // 提取字符串(带长度) Py_ssize_t str_len; const char* utf8_content_with_len = PyUnicode_AsUTF8AndSize(str_obj, &str_len); // 使用提取的内容 printf("字符串内容:%s\n", utf8_content); printf("字符串长度:%zd,内容:%.*s\n", str_len, (int)str_len, utf8_content_with_len); }
关于转bytes的问题
转成bytes再用PyBytes_AsStringAndSize是多此一举,而且会引入编码问题(需要显式指定编码,比如str.encode('utf-8')),直接用Unicode API提取是最直接的方案。如果调用PyBytes_AsStringAndSize报错,就是因为传入的不是bytes对象,这是正常的类型校验结果。
构造可被PyUnicode_Check识别的对象
在C API中,用PyUnicode_FromUTF8("你的字符串")或PyUnicode_FromString("你的字符串")创建的对象,必然能被PyUnicode_Check识别。D语言调用时,要确保调用的是Python 3的这些API,而非Python 2的旧函数。
内容的提问来源于stack exchange,提问作者Nordlöw
相关产品推荐
相关产品推荐

