Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/selenium/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Cython-动态2D C+的记忆视图+;排列 目标:< /强>使用Cython获取2D C++字符数组中的内存视图。_Python_Cython_Typed Memory Views_Pep3118 - Fatal编程技术网

Python Cython-动态2D C+的记忆视图+;排列 目标:< /强>使用Cython获取2D C++字符数组中的内存视图。

Python Cython-动态2D C+的记忆视图+;排列 目标:< /强>使用Cython获取2D C++字符数组中的内存视图。,python,cython,typed-memory-views,pep3118,Python,Cython,Typed Memory Views,Pep3118,一点背景: 我有一个本地C++库,它生成一些数据并通过 char ** /代码>返回到Cython世界。阵列在库中初始化和操作如下: struct Result\u缓冲区{ 字符**数据\指针; 整数长度=0; 结果缓冲区(整数行容量){ 数据指针=新字符*[行容量]; 返回arr; } //实际数据被逐行追加 无效附加行(字符*行数据){ 数据指针[长度]=行数据; 长度++; } } 所以我们基本上得到一个嵌套子数组的数组 旁注: -每行的列数相同 -行可以共享内存,即指向同一行

一点背景:

我有一个本地C++库,它生成一些数据并通过<代码> char ** /代码>返回到Cython世界。阵列在库中初始化和操作如下:

struct Result\u缓冲区{
字符**数据\指针;
整数长度=0;
结果缓冲区(整数行容量){
数据指针=新字符*[行容量];
返回arr;
}
//实际数据被逐行追加
无效附加行(字符*行数据){
数据指针[长度]=行数据;
长度++;
}     
}
所以我们基本上得到一个嵌套子数组的数组

旁注:
-每行的列数相同
-行可以共享内存,即指向同一行数据

目标是更好地将此阵列与memoryview一起使用,而无需昂贵的内存复制


第一次进近(不工作)使用Cython数组和内存视图:

下面是.pyx文件,它应该使用生成的数据

来自cython cimport视图的

cimport numpy作为np
将numpy作为np导入
[...]
def原始数据到numpy(自):
#源阵列的维度
cdef int ROWS=self.\u row\u count
cdef int COLS=自列计数
这是C++库中的数组,是由CealTyBuffor()创建的
cdef char**raw\U data\U pointer=self.\U raw\U data
#它仅适用于指向第一个嵌套数组的指针
cdef char*指向0的指针=原始数据指针[0]
#现在创建一个2D Cython阵列
cdef view.array cy\U array=指向0的指针
#有了这些,我们最终可以创建NumPy阵列:
返回np.asarray(cy_数组)
这实际上是编译良好,运行时不会崩溃,但结果并不是我所期望的。如果我打印出NumPy数组的值,我会得到以下结果:

000: [1, 2, 3, 4, 5, 6, 7, 8, 9]
001: [1, 0, 0, 0, 0, 0, 0, 113, 6]
002: [32, 32, 32, 32, 96, 96, 91, 91, 97]
[...]
结果表明,第一行映射正确,但其他行看起来更像未初始化的内存。因此,可能与
char**
的内存布局和2D MemoryView的默认模式不匹配


编辑#1:我从中了解到,内置cython阵列不支持间接内存布局,因此我必须为
无符号字符**
创建cython包装,它公开了解决方案: 手动执行缓冲协议:

包装类,用于包装
无符号字符**
,并实现缓冲区协议(Indirect2DArray.pyx):

产生以下输出:

[1, 2, 3, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9, 1, 2, 3, 7, 8, 9, 1, 2, 3, 4, 5, 6, 2, 1, 4]
[2, 1, 3, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9, 1, 2, 3, 7, 8, 9, 1, 2, 3, 4, 5, 6, 1, 2, 4]
[3, 1, 2, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9, 1, 2, 3, 7, 8, 9, 1, 2, 3, 4, 5, 6, 1, 2, 3]

这正是我所期望的。感谢所有帮助我的人

我认为你不能直接从
char**
进入记忆视图。我认为您需要创建一个
cdef类,该类封装
char**
,然后从中创建memoryview。如果行的维度可能不同,则类型
char**
才有意义(性能和清晰度方面),但内存视图不是正确的工具。如果所有行都有相同的维度,那么返回连续内存作为
char*
(n倍m长)就更好了-在这种情况下,我会更改接口。好的,我需要更准确地说明源arrray是如何创建的:(我编辑了原始帖子)。此处使用
char**
的原因是多行(按第一维度索引)可以共享内存,即指向同一第二维度数组。因此,将连续内存返回为“char*”将扼杀“行共享”的好处。我认为,如果您执行
cdef unsigned char[::view.indirect_continuous,::1]arr=wrapper
,它应该会像预期的那样工作。此外,最好将您的编辑提取为自我回答-现在的问题(+答案)太长了。
def test_wrapper(self):
    cdef nrows= 10000
    cdef ncols = 81    

    cdef unsigned char** raw_pointer = self.raw_data
    wrapper = Indirect2DArray(nrows,ncols)    
    wrapper.set_raw_data(raw_pointer)

    # now create the memoryview:
    cdef unsigned char[::view.indirect_contiguous, ::1] view = wrapper

    # print some slices 
    print(list(view[0,0:30]))
    print(list(view[1,0:30]))
    print(list(view[2,0:30]))
[1, 2, 3, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9, 1, 2, 3, 7, 8, 9, 1, 2, 3, 4, 5, 6, 2, 1, 4]
[2, 1, 3, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9, 1, 2, 3, 7, 8, 9, 1, 2, 3, 4, 5, 6, 1, 2, 4]
[3, 1, 2, 4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9, 1, 2, 3, 7, 8, 9, 1, 2, 3, 4, 5, 6, 1, 2, 3]