2017-01-20 10 views
1

나는 bytes 객체를 가리키는 파이썬 memoryview을 가지고 있는데,이 객체는 cython에서 일부 처리를 수행하고 싶습니다.바이트 객체에 파이썬 메모리 뷰에 대한 포인터를 얻는 것

내 문제는 다음 bytes 객체가 쓸 수 없기 때문에

  • 는 사이 썬은 그것에서 형식화 (사이 썬) memoryview을 구성 할 수 없습니다
  • 내가 포인터를 얻을 수 없기 때문에 나도 포인터를 사용할 수 없습니다 에서

    다음 memoryview는

예 시작 BufferError: memoryview: underlying buffer is not writable

하나가이 문제를 해결 않습니다 방법 : 파이썬 : 사이 썬에서

array = memoryview(b'abcdef')[3:] 

:

  • cdef char[:] my_view = arrayCannot take address of Python variable는 메시지와 함께 런타임에 실패

    • cdef char * my_ptr = &array[0]는 메시지와 함께 컴파일에 실패 ?

  • +0

    첫 번째 질문 : 어떻게 당신이 '배열'인수를 선언합니까 Cython 기능? –

    +0

    @PierredeBuyl 파이썬 객체로 전달합니다. 다음과 같이 : Cython :'def myfunc (arr) : pass' – ARF

    +0

    안녕하세요, 일부 문서를보고 인터넷 검색을 한 다음,받은 모든 정보가 메모리보기이면 읽기 - 쓰기 액세스가 어려워 보입니다. 먼저 메모리 뷰가 어떻게 만들어 졌는지 언급해야합니다.대신에'Py_buffer' 구조체를 얻을 수 있다면 도움이 될 것입니다. https://docs.python.org/3.5/c-api/buffer.html –

    답변

    1

    bytearray을 사용하여 변경 가능한 메모리 뷰를 만들 수 있습니다. 이는 아마 일을하는 올바른 방법입니다 bytearray (@ CheeseLover의 대답에 따라)를 사용 bytearray

    data = bytearray('python') 
    view = memoryview(data) 
    view[0] = 'c' 
    print data 
    # cython 
    
    +0

    실제로. 그게 바로 지금하고있는 일입니다. 그러나 임시 'bytearray'객체를 인스턴스화하면 알고리즘 속도를 높이기 위해 cython을 사용하는 모든 목적을 무효화 할 수 있습니다. – ARF

    0

    , 문자열을 변경되지 않습니다. 내 충고는 bytearrays에서 전적으로 작업하여 임시 변환을 피하는 것입니다. 그러나 : -

    char* can be directly created from a Python string (또는 bytes)은 링크 섹션의 끝을 참조하십시오

    cdef char * my_ptr = array 
    # you can then convert to a memoryview as normal in Cython 
    cdef char[:] mview = <char[:len(array)]>my_ptr 
    

    경고의 몇 : 수정하려고하면

    1. bytes가 변경할 수없는 것을 기억하고 해당 메모리보기가 문제를 일으킬 수 있습니다.
    2. my_ptr (따라서 mview)은 array이 유효하면 유효합니다. 그래서, 같은 당신이 액세스 TI의 데이터를 필요로하기위한 array에 대한 참조를 유지해야
    +0

    감사합니다. 내 문제는, 내가'바이트'개체를 부여 오전입니다. 따라서 인스턴스화 비용을 들이지 않고'bytesarray'로 전환 할 수 없습니다. 'char *'는'bytes()'에서 만들 수 있지만'memoryview (bytes())'에서 만들 수 없습니다. 'TypeError : expected bytes, memoryview found'와 함께 제안이 실패했습니다. – ARF

    +0

    아, 미안 해요. 약간 잘못 이해했습니다. 'array.obj'를 사용하여 memoryview에서 (다시 복사하는 일없이)'bytes'를 얻을 수 있습니다 (파이썬> = 3.3 만). 그런 다음 그것을'char *'에 캐스팅합니다. – DavidW

    +0

    나는 그것을 시도했습니다. memoryview의 오프셋. test.obj == b'abcdef '동안'test = memoryview (b'abcdef') [3 :]''바이트 (test) == b'def''이다. 지금까지 찾은 유일한 해결책은 내 답변에있는 매우 자세한 절차입니다. - 그 끔찍한 코드 혼란을 없애고 싶지만. – ARF

    2

    좋아, 난의 bytes 객체의 버퍼에 대한 포인터를 얻을 수있는 해결책을 발견 파이썬 API를 통해 파고 후 memoryview (여기서 bytes_view = memoryview(bytes())). 어쩌면 이것은 다른 사람을 도울 수 있습니다 :

    from cpython.buffer cimport PyObject_GetBuffer, PyBuffer_Release, PyBUF_ANY_CONTIGUOUS, PyBUF_SIMPLE 
    
    
    cdef Py_buffer buffer 
    cdef char * my_ptr 
    
    PyObject_GetBuffer(bytes, &buffer, PyBUF_SIMPLE | PyBUF_ANY_CONTIGUOUS) 
    try: 
        my_ptr = <char *>buffer.buf 
        # use my_ptr 
    finally: 
        PyBuffer_Release(&buffer) 
    
    +1

    정확히 내가 무엇을 찾고 ..하지만 귀하의 코드에 buffer_view 무엇입니까? "버퍼"를 의미합니까? –

    +1

    방금 ​​시도했지만,'buffer_view'는'buffer' 여야합니다. –

    +0

    @ConradParker 메모 주셔서 감사합니다. 내 코드에서 스 니펫을 복사하고이를 단순화하면서 변수 이름을 사용하여 명확하게했습니다. 나는 분명히 하나를 놓쳤다. 코드 스 니펫이 현재 당신을 위해 일하고 있는가? – ARF