TypeError:“char const*”类型的参数

2024-05-12 18:30:02 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前正在和Freeswitch及其event socket library(通过mod event socket)一起工作。例如:

from ESL import ESLconnection

cmd = 'uuid_kill %s' % active_call # active_call comes from a Django db and is unicode
con = ESLconnection(config.HOST, config.PORT, config.PWD)
if con.connected():
    e = con.api(str(cmd))
else:
    logging.error('Couldn\'t connect to Freeswitch Mod Event Socket')

如您所见,我必须用str()显式地转换con.api()的参数。如果不这样做,调用将在以下堆栈跟踪中结束:

Traceback (most recent call last):
  [...]
    e = con.api(cmd)
  File "/usr/lib64/python2.7/site-packages/ESL.py", line 87, in api
    def api(*args): return apply(_ESL.ESLconnection_api, args)
TypeError: in method 'ESLconnection_api', argument 2 of type 'char const *'

我不明白这个类型错误:它是什么意思?cmd包含一个字符串,那么当我用str(cmd)进行转换时,它会修复它吗?
它是否与Freeswitch通过SWIG生成的python API相关?


Tags: infromcmdeventapiconfigargssocket
2条回答

我也有类似的问题,我通过这样做来解决: cmd = 'uuid_kill %s'.encode('utf-8')

简而言之:cmd可能包含一个Unicode字符串,不能简单地将其转换为const char *。错误消息可能来自包装器框架,该框架自动为C库(如SWIG或ctypes)编写Python绑定。该框架知道如何处理字节字符串,但对Unicode字符串进行punt操作。传递str(cmd)有帮助,因为它将Unicode字符串转换为字节字符串,从中可以轻松提取C代码所需的const char *值。

长答案:

C类型char const *,通常拼写为const char *,可以读取为“只读的char数组,char是C拼写“byte”的方式。当C函数接受const char *时,它需要一个“C字符串”,即以空字符结尾的char值数组。方便的是,Python字符串在内部表示为C字符串,并带有一些附加信息,如类型、引用计数和字符串长度(因此可以以O(1)的复杂度检索字符串长度,并且字符串本身可能包含空字符)。

Python 2中的Unicode字符串表示为Py_UNICODE数组,其宽度为16位或32位,具体取决于操作系统和构建时标志。这样的数组不能传递给需要8位字符数组的代码-它需要转换,通常需要转换为临时缓冲区,并且在不再需要时必须释放该缓冲区。

例如,对于C函数strlen,一个简单的(而且非常不必要的)包装可能如下所示:

PyObject *strlen(PyObject *ignore, PyObject *obj)
{
  const char *c_string;
  size_t len;
  if (!PyString_Check(obj)) {
    PyErr_Format(PyExc_TypeError, "string expected, got %s", Py_TYPE(obj)->tp_name);
    return NULL;
  }
  c_string = PyString_AsString(obj);
  len = strlen(c_string);
  return PyInt_FromLong((long) len);
}

代码只需调用PyString_AsString来检索由每个Python字符串存储并由strlen预期的内部C字符串。为了使此代码也支持Unicode对象(如果在Unicode对象上调用strlen甚至是有意义的话),它必须显式地处理它们:

PyObject *strlen(PyObject *ignore, PyObject *obj)
{
  const char *c_string;
  size_t len;
  PyObject *tmp = NULL;
  if (PyString_Check(obj))
    c_string = PyString_AsString(obj);
  else if (PyUnicode_Check(obj)) {
    if (!(tmp = PyUnicode_AsUTF8String(obj)))
      return NULL;
    c_string = PyString_AsString(tmp);
  }
  else {
    PyErr_Format(PyExc_TypeError, "string or unicode expected, got %s",
                 Py_TYPE(obj)->tp_name);
    return NULL;
  }
  len = strlen(c_string);
  Py_XDECREF(tmp);
  return PyInt_FromLong((long) len);
}

注意额外的复杂性,不仅在样板代码行中,而且在不同的代码路径中,它们需要对保存Unicode字符串字节表示的临时对象进行不同的管理。还要注意的是,在将Unicode字符串转换为字节字符串时,决定使用编码所需的代码。UTF-8可以保证对任何Unicode字符串进行编码,但是将UTF-8编码的序列传递给需要C字符串的函数在某些情况下可能没有意义。str函数使用ASCII编解码器对Unicode字符串进行编码,因此,如果Unicode字符串实际包含任何非ASCII字符,则会出现异常。

已经有了requests to include this functionality in SWIG,但是从链接的报告中还不清楚他们是否加入了。

相关问题 更多 >