python - 如何将一片 memoryview 转换为 C 字符串(unsigned char*)?

标签 python cython memoryview

下面是我遇到这个问题的代码:

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

对于一个简单的例子来说,这可能是代码太多了,但如果你仔细想想,其实并没有那么多。循环之前的部分处理过滤掉各种边缘情况——他们对这个问题不感兴趣。唯一重要的部分是第一个参数必须实现缓冲区协议(protocol),第二个参数是文件名。

因此,为了写入文件,我想获取内存 View 的一部分,然后将其传递给需要指向 unsigned char 的指针的 C 函数。对于我的一生,我不知道如何使用 Cython 来做到这一点......我尝试了上面代码的各种排列,但是,在大多数情况下我得到了

Storing unsafe C derivative of temporary Python reference

没有任何关于它试图生成什么的提示。

上面的代码中也有一些重复,因为我不知道如何使用 in_view.buf[x] 并使其具有我需要的类型。我把它留在这里只是为了表明我也尝试过。


类似问题的答案无效,因为 Cython 内存 View 存在错误。如果有不同的答案,我将不胜感激。

最佳答案

鉴于您似乎无法使用内存 View ,因为数据是只读的,您可以使用 Py_Buffer对象代替。数据存储为 void*in_view.buf .将其转换为 const char*<const char*>(in_view.buf) .你可以获得 n th 元素通过简单的指针算法(即只需将 n 添加到该值)。

自从您使用了 PyBuf_SIMPLE您知道项目大小为 1 且数组是连续的,但在更复杂的情况下,您可能不得不担心这一点。

关于python - 如何将一片 memoryview 转换为 C 字符串(unsigned char*)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48136122/

相关文章:

python - 更改 Cython 对 .so 文件的命名规则

python - Cython:内联函数不是纯 C

python - 哪个更快 np.vstack、np.append、np.concatenate 或在 cython 中制作的手动函数?

c - 如何在 Cython 中动态声明二维 c 数组

android - Android Studio 有 NDK 内存查看器吗?

python - 如何防止命令行窗口在出错后关闭

python - CNF 真值表

python - itertools.product - 返回列表而不是元组

python - Cython 重载 "no suitable method found"

python - 用于 Lucas-Lehmer 素数测试的更快的按位模数