2017-05-09 1 views
1

내가 외부 라이브러리에 다음 함수가 있다고 가정 :ctypes를 사용하여 바이트 및 바이트 객체를 모두 외부 라이브러리로 효율적으로 전달할 수 있습니까?

void foo(const unsigned char *buf, const int len); 
내가 버퍼의 복사본을 만들지 않고, ctypes를 사용하여 내 파이썬 코드에서이 함수를 호출 할 수 있도록하고 싶습니다

. 버퍼가 상당히 클 수 있으므로 사본을 피하는 것이 명백한 성능 이점을 갖습니다. 그리고 내 코드의 소비자의 편의를 위해이 버퍼를 bytes 또는 bytearray으로 제공 할 수 있기를 바랍니다.

지금 으로 buf을 선언합니다. 내 argtypes 선언에.

lib.foo.argtypes = [ctypes.POINTER(ctypes.c_char), ctypes.c_int] 
buf = bytes(...) 
lib.foo(buf, len(buf)) 

잘 작동하며 bytes 개체를 전달할 수 있습니다. 나는 다음 bytearray 개체를 전달할 경우, 나는 다음과 같은 오류가 발생 :

ctypes.ArgumentError: argument 1: : wrong type

bytearraybytes, 바람직 상호 교환, 전달 될 수 있도록 저를위한 방법이 있나요?

+0

@eryksun 응답 해 주셔서 감사합니다. 나는 이것이 어떻게 성취되었는지에 대한 진실한 염려가 없다. 방금 외부 코드가 버퍼 내용을 복사하지 않고'const unsigned char * '를 받길 원합니다. 가능하다면. –

답변

1

from_param을 무시하고 bytearray에 맞게 포인터 유형의 하위 클래스를 만들 수 있습니다. 예를 들어

class Pchar(ctypes.POINTER(ctypes.c_char)): 
    _type_ = ctypes.c_char 
    @classmethod 
    def from_param(cls, param, array_t=ctypes.c_char * 0): 
     if isinstance(param, bytearray): 
      param = array_t.from_buffer(param) 
     return super(Pchar, cls).from_param(param) 

lib.foo.argtypes = [Pchar, ctypes.c_int] 

bytearray 위해 만들어지는 c_char 배열은 파이썬 버퍼 프로토콜을 통해 물체의 내부 버퍼를 얻을 필요가있다. 배열 크기는 중요하지 않으므로 bytearray의 가능한 모든 길이에 대해 배열 하위 클래스를 만들지 않아도됩니다. from_param 인수 목록에 캐시 된 길이 0 배열 유형을 사용하기 만하면됩니다.

+0

다시 한번 감사드립니다. Eryk, 정말 당신에게 맥주 빚이 있습니다! –

+0

* from_param 인수 목록에 캐시 됨 *. 나는 그것에 관심이 있었다. 'ctypes._CData'에 정의 된 classmethod에는'array_t' 인자가 없습니다, 맞습니까? 여기에는 param이라는 이름의 하나의 인수 만 있습니다. 그러나 어떤 호출자도 결코 제공하지 않는 이름의 인자 인'array_t'를 추가했습니다. 이렇게하면 모듈로드시 기본값이 계산되므로 시간이 많이 소요될 수 있습니다. 그렇게하면 한 번만 비용을 지불하게됩니다. 그 맞습니까? 전에이 기술을 접한 적이 없어요! –

+1

@DavidHeffernan, 조회 목록을 약간 최적화하기 위해 인수 목록을 사용했습니다. 약간 더 느린 클래스 속성을 사용할 수있었습니다. 또한 ctypes.c_char * 0에 의해 생성 된 타입을 ctypes가 캐시하는 방법에 의존 할 수 있습니다. 후자의 경우 매번 바이트 코드를 실행하고'sq_repeat' 함수를 호출하고, 결국'PyCArrayType_from_ctype'을 호출합니다.이 타입은 튜플 키'(c_char, 0)'에 따라 캐시 타입을 반환합니다. 이것은 많은 것처럼 보일지 모르지만 실제로는 새로운 유형의 객체를 만드는 비용과 비교할 때 상대적으로 싸기 때문에 ctypes에 유형 캐시가있는 이유입니다. – eryksun

관련 문제