我目前正在和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相关?
我也有类似的问题,我通过这样做来解决:
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
,一个简单的(而且非常不必要的)包装可能如下所示:代码只需调用
PyString_AsString
来检索由每个Python字符串存储并由strlen
预期的内部C字符串。为了使此代码也支持Unicode对象(如果在Unicode对象上调用strlen
甚至是有意义的话),它必须显式地处理它们:注意额外的复杂性,不仅在样板代码行中,而且在不同的代码路径中,它们需要对保存Unicode字符串字节表示的临时对象进行不同的管理。还要注意的是,在将Unicode字符串转换为字节字符串时,决定使用编码所需的代码。UTF-8可以保证对任何Unicode字符串进行编码,但是将UTF-8编码的序列传递给需要C字符串的函数在某些情况下可能没有意义。
str
函数使用ASCII编解码器对Unicode字符串进行编码,因此,如果Unicode字符串实际包含任何非ASCII字符,则会出现异常。已经有了requests to include this functionality in SWIG,但是从链接的报告中还不清楚他们是否加入了。
相关问题 更多 >
编程相关推荐