我使用Python 2 API包装了很多C++(由于各种技术原因,我不能使用像swig或boost.python这样的东西).当我必须将一个字符串(通常是一个路径,总是ASCII)传递给C/C++时,我使用这样的东西:
std::string file_name = PyString_AsString(py_file_name);
if (PyErr_Occurred()) return NULL;
Run Code Online (Sandbox Code Playgroud)
现在我正在考虑更新到Python 3,其中PyString_*不存在方法.我找到了一个解决方案,说我应该这样做:
PyObject* bytes = PyUnicode_AsUTF8String(py_file_name);
std::string file_name = PyBytes_AsString(bytes);
if (PyErr_Occurred()) return NULL;
Py_DECREF(bytes);
Run Code Online (Sandbox Code Playgroud)
然而,这是两倍的行,看起来有点难看(更不用说如果我忘记了最后一行,它可能会引入内存泄漏).
另一种选择是重新定义python函数以bytes对象进行操作,并像这样调用它们
def some_function(path_name):
_some_function(path_name.encode('utf8'))
Run Code Online (Sandbox Code Playgroud)
这并不可怕,但它确实需要每个函数的python端包装器.
有没有更清洁的方法来处理这个?
我需要在 python 对象和各种编码的 c 字符串之间进行转换。使用 PyUnicode_Decode 从 ac 字符串到 unicode 对象相当简单,但是我不知道如何走另一条路
//char* can be a wchar_t or any other element size, just make sure it is correctly terminated for its encoding
Unicode(const char *str, size_t bytes, const char *encoding="utf-16", const char *errors="strict")
:Object(PyUnicode_Decode(str, bytes, encoding, errors))
{
//check for any python exceptions
ExceptionCheck();
}
Run Code Online (Sandbox Code Playgroud)
我想创建另一个函数,它接受 python Unicode 字符串并使用给定的编码将其放入缓冲区中,例如:
//fills buffer with a null terminated string in encoding
void AsCString(char *buffer, size_t bufferBytes,
const char *encoding="utf-16", const char *errors="strict")
{
... …Run Code Online (Sandbox Code Playgroud)