2014-05-25 19 views
9

Python'un farklı sürümlerindeki bu davranışla kafam karıştı ve neden anlamadım?Farklı ktypes davranışı c_char_p?

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 

Biri diğeri bana bir hata verirken çalışır. Hangisi doğru ?

Her ikisi de doğruysa, 3.3.5'te 2.7 ile aynı davranışı nasıl başarabilirim? Ben char işaretçisini python'dan C'ye geçmek istiyorum.

+2

Python 3'te 'bytes' kullanın, yani c = b" merhaba "'. 'C_char_p' örneği, 'bytes' nesnesinin özel arabelleğini işaret eder, bu nedenle yalnızca dizeyi değiştirmeyecek" const "parametreleri için kullanın. – eryksun

+0

@eryksun Bunu python3'te neden değiştiğine dair bir cevap olarak ekleyebilirseniz, bunu kabul etmekten mutluluk duyarım. –

cevap

13

c_char_p, _SimpleCData'un bir alt sınıfıdır, _type_ == 'z'. __init__ yöntemi, basit 'z' türü z_set için olan setfunc türünü çağırır.

Python 2'de, str ve unicode dizgilerini işlemek için z_set function (2.7.7) yazılmıştır. Python 3'ten önce str, 8 bitlik bir dizedir. CPython 2.x str dahili olarak C null sonlandırılmış bir dize (yani \0 ile sonlandırılan bir bayt dizisi) kullanır, bu nedenlePyString_AS_STRING'u arayabilir (yani str nesnesinin iç arabelleğine bir işaretçi edinin). Bir unicode dizesinin önce bir bayt dizgisine kodlanması gerekir. z_set bu kodlamayı otomatik olarak işler ve _objects özniteliğinde kodlanmış dizeye bir başvuru tutar. Windows'ta

>>> c = u'spam' 
>>> a = c_char_p(c) 
>>> a._objects 
'spam' 
>>> type(a._objects) 
<type 'str'> 

, varsayılan ctypes dize kodlama hatası 'ignore' için set taşıma ile 'mbcs' olduğunu. Diğer tüm platformlarda varsayılan kodlama, 'strict' hata işleme ile 'ascii' olur. Varsayılanı değiştirmek için ctypes.set_conversion_mode'u arayın. Örneğin, set_conversion_mode('utf-8', 'strict').

Python 3'te, z_set function (3.4.1), str (şimdi Unicode) değerini bytes'a otomatik olarak dönüştürmez. Python 3'te paradigma, karakter dizilerini ikili verilerden kesin olarak bölmek için kaydırdı. Varsayılan varsayılan dönüşümler, set_conversion_mode işlevinin olduğu gibi kaldırıldı. c_char_p a bytes nesnesini (ör. b'spam' veya 'spam'.encode('utf-8')) geçmek zorundasınız. CPython 3.x'te nesnesinin iç arabelleğine bir işaretçi almak için PyBytes_AsString numaralı C-API işlevini z_set çağırır.

C işlevi dizeyi değiştirirse,dizisini oluşturmak için bunun yerine create_string_buffer kullanmanız gerektiğini unutmayın. c_char_p'u kullanmanın güvenli olduğunu bilmek için const olarak yazılacak bir parametre arayın.

+0

Detaylı cevabınız için teşekkürler. –