ctypes c_char_p的不同行为?

时间:2014-05-25 05:24:44

标签: python python-2.7 python-3.x ctypes

我对不同版本的python的这种行为感到困惑,不明白为什么?

Python 2.7.5 (default, Aug 25 2013, 00:04:04) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> c="hello"
>>> a=ctypes.c_char_p(c)
>>> print(a.value) 
hello

Python 3.3.5 (default, Mar 11 2014, 15:08:59) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.2.79)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> c="hello" 
>>> a=ctypes.c_char_p(c)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: bytes or integer address expected instead of str instance

一个有效,而另一个给我一个错误。哪一个是正确的?

如果两者都正确,我怎样才能达到与3.3.5中2.7相同的行为?我想将char指针从python传递给C.

1 个答案:

答案 0 :(得分:17)

c_char_p_SimpleCData的子类,_type_ == 'z'__init__方法调用类型setfunc,对于简单类型'z'z_setstr

在Python 2中,编写z_set function(2.7.7)来处理unicodestr字符串。在Python 3之前,str是一个8位字符串。 CPython 2.x \0在内部使用一个以C结尾的字符串(即由z_set终止的字节数组),str可以调用PyString_AS_STRING(即得到一个指向unicode对象的内部缓冲区的指针。首先需要将z_set字符串编码为字节字符串。 _objects自动处理此编码,并在>>> c = u'spam' >>> a = c_char_p(c) >>> a._objects 'spam' >>> type(a._objects) <type 'str'> 属性中保留对已编码字符串的引用。

'mbcs'

在Windows上,默认的ctypes字符串编码为'ignore',错误处理设置为'ascii'。在所有其他平台上,默认编码为'strict',错误处理为set_conversion_mode('utf-8', 'strict')。要修改默认值,请致电ctypes.set_conversion_mode。例如,str

在Python 3中,z_set function(3.4.1)不会自动将bytes(现在为Unicode)转换为set_conversion_mode。范例在Python 3中转移到严格划分二进制数据中的字符串。删除了ctypes默认转换,函数c_char_p也是如此。您必须传递bytes b'spam'个对象(例如'spam'.encode('utf-8')z_set)。在CPython 3.x中,bytes调用C-API函数PyBytes_AsString来获取指向c_char对象的内部缓冲区的指针。

请注意,如果C函数修改了字符串,则需要使用create_string_buffer来创建const数组。查找要输入c_char_p的参数,以便知道使用{{1}}是安全的。