TypeError:'char const*'类型的参数

Ant*_*nto 6 python freeswitch

我目前正在使用Freeswitch及其事件套接字库(通过mod事件套接字).例如:

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')
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我不得不明确地con.api()使用str().没有它,调用将在以下堆栈跟踪中结束:

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 *'
Run Code Online (Sandbox Code Playgroud)

我不明白这个TypeError:这是什么意思? cmd包含一个字符串,那么当我使用它时它会修复它str(cmd)
它可能与通过SWIG生成的Freeswitch的python API有关吗?

use*_*342 11

简答:cmd可能包含一个Unicode字符串,不能简单地转换为const char *.错误消息可能来自一个包装器框架,它自动为C库编写Python绑定,例如SWIG或ctypes.框架知道如何处理字节字符串,但是在Unicode字符串上发挥作用.传递str(cmd)帮助,因为它将Unicode字符串转换为字节字符串,从中const char *可以轻松地提取C代码所期望的值.

答案很长:

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

Python 2中的Unicode字符串表示为Py_UNICODE16或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);
}
Run Code Online (Sandbox Code Playgroud)

代码只是调用PyString_AsString以检索由每个Python字符串存储的内部C字符串strlen.对于此代码也支持Unicode对象(假设它甚至可以调用strlenUnicode对象),它必须显式处理它们:

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);
}
Run Code Online (Sandbox Code Playgroud)

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

有人要求在SWIG中包含此功能,但是如果链接报告中有这些功能,则不清楚.