2017-12-02 1 views
-2

바이트 개체는 immutable입니다. 이 항목 할당을 지원하지 않습니다왜 Python 3에서 ctypes를 사용하여 변경할 수없는 바이트 객체를 수정할 수 있습니까?

>>> bar = b"bar" 
>>> bar[0] = b"#" 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'bytes' object does not support item assignment 

STR 객체는 불변 :

>>> bar = "bar" 
>>> bar[0] = "#" 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
TypeError: 'str' object does not support item assignment 

STR 객체와 동일한 작업을 수행 할 수없는 상태 바이트하는 ctypes 객체를 수정하는 것이 가능하다. 이유를 설명해 주시겠습니까? 다음 예제를 살펴보십시오.

C 코드

char* foo(char *bar) { 
    bar[0] = '#'; 
    return bar; 
} 

C 코드를 컴파일

gcc -shared -o clib.so -fPIC clib.c 

바이트를 시도

파이썬 코드

,536,913,632 10
import ctypes 

clib = ctypes.CDLL('./clib.so') 

bar = b"bar" 
print("Before:", bar, id(bar)) 

clib.foo(bar) 
print("After: ", bar, id(bar)) 

파이썬 코드 출력

Before: b'bar' 140451244811328 
After: b'#ar' 140451244811328 

str을 시도

STR 객체는 파이썬 3에서 불변하지만, 바이트는 달리이하는 ctypes으로 수정할 수는 없습니다 객체.

파이썬 코드

import ctypes 

clib = ctypes.CDLL('./clib.so') 

bar = "bar" 
print("Before:", bar, id(bar)) 

clib.foo(bar) 
print("After: ", bar, id(bar)) 

파이썬 3

Before: bar 140385853714080 
After: bar 140385853714080 
+0

여러분은 막후에서 벗어나므로 기본적으로 어떤 것도 가능합니다. –

+0

좋아, 나는 그것을 받아 들일 수 있었지만 왜 str 객체로 같은 것을 할 수 없는지? –

+0

문자열 시도에 대한 코드를 표시 할 수 있습니까? –

답변

2

str 유니 코드로 추출하고, 1, 2, 또는 저장 될 수 파이썬 코드 출력 4 바이트 문자열에 사용 된 가장 높은 유니 코드 문자에 따라 문자열 당. 문자열을 C 함수에 전달하려면 특정 표현으로 변환해야합니다. 이 경우 ctypes은 변환 된 임시 버퍼를 원본이 아니라 C로 전달합니다. ctypes은 프로토 타입 함수가 잘못되었거나 내용을 변경하는 함수에 불변의 객체를 보내는 경우 Python을 손상시키고 손상시킬 수 있으며 이러한 경우주의해야합니다.

bytes 케이스에서 ctypes은 바이트의 내부 버퍼에 대한 포인터를 따라 전달되지만 수정 될 것으로 기대하지는 않습니다. 고려 : 불변

a = b'123' 
b = b'123' 

bytes 때문에, 파이썬은 ab 모두에서 동일한 참조를 저장 무료입니다. bctypes-wrapped 함수에 전달하고 수정하면 a도 손상 될 수 있습니다.스트레이트 ctypes documentation에서

:

당신은 조심해야하지만, 변경 가능한 메모리에 대한 포인터를 기대 함수 [불변의 객체]를 통과하지. 가변 메모리 블록이 필요하다면, ctypes는 다양한 방법으로 이것을 생성하는 create_string_buffer() 함수를 가지고 있습니다 ...

관련 문제