【问题标题】:How Does String Conversion Between PyUnicode String and C String Work? [closed]PyUnicode 字符串和 C 字符串之间的字符串转换是如何工作的? [关闭]
【发布时间】:2016-03-18 19:55:50
【问题描述】:

我有一个 PyUnicode 对象,我正在尝试将其转换回 C 字符串 (char *)。

我尝试这样做的方式似乎不起作用。这是我的代码:

PyObject * objectCompName = PyTuple_GET_ITEM(compTuple, (Py_ssize_t) 0);
PyObject * ooCompName = PyUnicode_AsASCIIString(objectCompName);
char * compName = PyBytes_AsString(ooCompName);
Py_DECREF(ooCompName);

还有其他/更好的方法我应该这样做吗?

【问题讨论】:

  • 定义“似乎不起作用”。你会崩溃吗?结果与您想要的不同?无论哪种情况,究竟是什么?
  • 您使用的是哪个版本的 Python?
  • @JohnBollinger 它到达这里时会出现段错误。 Python 3.
  • 对我的问题和答案都投反对票的任何理由?
  • 您不会检查 API 调用的返回值,也不会测试是否引发了异常。这将是一个很好的起点。

标签: python c python-3.x python-c-api python-internals


【解决方案1】:

如果 UTF-8 编码的char * 没问题,你绝对应该使用PyUnicode_AsUTF8AndSize(需要 Python 3.3):

PyObject * objectCompName = PySequence_GetItem(compTuple, 0);
if (! objectCompName) {
    return NULL;
}

Py_ssize_t size;
char *ptr = PyUnicode_AsUTF8AndSize(objectCompName, &size);
if (!ptr) {
    return NULL;
}

// notice that the string pointed to by ptr is not guaranteed to stay forever,
// and you need to copy it, perhaps by `strdup`.

另外,请务必强制检查您在代码中执行的每个 Py* 函数调用的返回值。

如果compTuple 不是tuple,这里PyTuple_GetItem 将返回NULL,或者0 导致IndexError。如果objectCompName 不是str 对象,PyUnicode_AsUTF8AndSize 将返回NULL。当条件正确时,忽略返回值,CPython 会以SIGSEGV 崩溃。

【讨论】:

  • PyUnicode 字符串最初是在另一个 C 函数中使用 PyUnicode_DecodeASCII 生成的。
  • 在那种情况下PyUnicode_AsUTF8AndSize 很好。
  • 好的,很好。您声明检查返回值是“强制性的”。我确实计划检查它们,我只是没有像我想测试并确保它首先工作那样。检查返回值实际上是一个要求,还是你只是说这是一个很好的做法?
  • 是的,这绝对是强制性的,不仅是一种好的做法。
  • 正确,所以你告诉我我需要这些检查绝对是一件好事,因为现在我知道是什么导致了潜在的问题。谢谢。
【解决方案2】:

您需要首先将您的 python PyUnicode 转换为非 unicode python 字符串(在此处阅读更多信息:https://docs.python.org/2/c-api/unicode.html#ascii-codecs),然后您可以轻松地将结果转换为 char*

以下是帮助您继续的伪代码:

// Assumption: you have a variable named "pyobj" which is
// a pointer to an instance of PyUnicodeObject.

PyObject* temp = PyUnicode_AsASCIIString(pyobj);
if (NULL == temp) {
    // Means the string can't be converted to ASCII, the codec failed
    printf("Oh noes\n");
    return;
}

// Get the actual bytes as a C string
char* c_str = PyByteArray_AsString(temp);

// Use the string in some manner
printf("The python unicode string is: %s\n", c_str);

// Make sure the temp stuff gets cleaned up at the end
Py_XDECREF(temp);

【讨论】:

  • 带有PyByteArray_AsString(temp); 的行是段错误。
猜你喜欢
  • 2018-05-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-26
  • 1970-01-01
相关资源
最近更新 更多