3

以下は、この問題が発生しているコードです。

cpdef object encode_file(object fin, str fout):
    if not PyObject_CheckBuffer(fin):
        raise TypeError("fin must follow the buffer protocol")


    cdef Py_buffer in_view
    cdef int ret_code = PyObject_GetBuffer(fin, &in_view, PyBUF_SIMPLE)
    if ret_code < 0:
        raise TypeError("Couldn't get buffer from fin")

    cdef bytes py_filename = fout.encode()
    cdef char* cy_filename = py_filename
    cdef bytes py_mode = "w".encode()
    cdef const char* mode = py_mode
    cdef FILE* fd = fopen(<const char*>py_filename, <const char*>mode)
    if <size_t>fd == 0:
        raise FileNotFoundError(fout)

    cdef unsigned char out_buff[256]
    cdef size_t written = 0
    cdef size_t total_written = 0
    cdef size_t used = 0
    cdef size_t total_used = 0
    cdef size_t pad_start = 80

    cdef unsigned char[:] char_view = fin
    cdef unsigned char* char_slice

    while total_used < <size_t>in_view.len:
        char_view = char_view[used:]
        # This is the place where I get the error
        char_slice = char_view.buf
        used = encode_buffer(
            char_slice,
            in_view.len - used,
            out_buff,
            256,
            pad_start,
            80,
            &written,
        )
        pad_start = 80 - used % 80
        total_written += written
        total_used += used
        if fwrite(out_buff, sizeof(char), used, fd) != used:
            fclose(fd)
            raise Exception(
                "Couldn't write to file: {}. Bytes written: {}".format(
                    fout, total_used,
                ),
            )

    fclose(fd)

    print "used: {}, written: {}".format(used, total_written)
    return total_written

これは単純な例としては少し多すぎるコードかもしれませんが、考えてみればそれほど多くはありません。ループの前の部分は、あらゆる種類のエッジ ケースを除外することを扱います。それらは、この質問には関係ありません。唯一の重要な部分は、最初の引数がバッファ プロトコルを実装する必要があり、2 番目の引数がファイル名であることです。

したがって、ファイルに書き込むために、メモリ ビューのスライスを取得し、それを へのポインタを期待する C 関数に渡しますunsigned char。私の人生では、Cythonを使用してこれを行う方法を理解できません...上記のコードのあらゆる種類の順列を試しましたが、ほとんどの場合、取得しています

一時的な Python 参照の安全でない C 派生物の保存

それが何を生成しようとしていたかについてのヒントはありません。

in_view.buf[x]上記のコードには、使用方法と必要なタイプを持たせる方法がわからなかったため、重複がいくつかあります。私もそれを試したことを示すために、ここに残しました。


Cython メモリ ビューにはバグがあるため、同様の質問に対する回答は機能しません。別の回答をいただければ幸いです。

4

1 に答える 1

1

データが読み取り専用であるためメモリビューを使用できないように思われる場合は、Py_Buffer代わりにオブジェクトを使用できます。データは in として保存されvoid*ますin_view.bufconst char*withにキャストし<const char*>(in_view.buf)ます。n単純なポインター演算 (つまりn、その値に追加するだけ)で th 要素を取得できます。

使用したのでPyBuf_SIMPLE、アイテムのサイズが 1 で、配列が連続していることはわかっていますが、より複雑なケースでは、これについて心配する必要があるかもしれません。

于 2018-01-07T16:28:27.557 に答える