簡體   English   中英

將 Python 3 Unicode 轉換為 std::string 的簡潔方法

[英]Clean Way to Convert Python 3 Unicode to std::string

我使用 Python 2 API 包裝了很多 C++(由於各種技術原因,我不能使用 swig 或 boost.python 之類的東西)。 當我必須將一個字符串(通常是一個路徑,總是 ASCII)傳遞到 C/C++ 中時,我使用這樣的東西:

std::string file_name = PyString_AsString(py_file_name); 
if (PyErr_Occurred()) return NULL; 

現在我正在考慮更新到 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); 

然而,這是行數的兩倍,看起來有點難看(更不用說如果我忘記了最后一行,它可能會導致內存泄漏)。

另一種選擇是重新定義 python 函數來操作bytes對象,並像這樣調用它們

def some_function(path_name):
    _some_function(path_name.encode('utf8'))

這並不可怕,但它確實需要每個函數的 python 端包裝器。

有沒有更干凈的方法來處理這個問題?

看起來解決方案存在於 python 3.3 中,帶有char* PyUnicode_AsUTF8(PyObject* unicode) 這應該與 Python 2 中的PyString_AsString()函數完全相同。

如果你知道(當然,你可以用斷言或類似的東西來檢查)它都是 ASCII,那么你可以簡單地像這樣創建它:

std::string py_string_to_std_string(PyUnicode_string py_file_name)
{
    len = length of py_file_name;     // Not sure how you write that in python. 
    std::string str(len); 
    for(int i = 0; i < len; i++)
        str += py_file_name[i]; 
    return str;
}

提供已接受答案的改進版本,而不是使用PyUnicode_AsUTF8(...)更好地使用PyUnicode_AsUTF8AndSize(...)

因為字符串可能在中間的某處包含空字符(0 代碼點),那么如果您使用PyUnicode_AsUTF8(...) ,則生成的std::string將包含完整字符串的截斷版本。

Py_ssize_t size = 0;
char const * pc = PyUnicode_AsUTF8AndSize(obj, &size);
std::string s;
if (pc)
    s = std::string(pc, size);
else
    // Error, handle!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM