Cython:从参考获得时缺少两个前元素的 Numpy 数组
Cython: Numpy array missing two first elements when obtained from reference
这是
最奇怪的错误,我试图从返回对向量的引用的 c++ 函数中获取一个 numpy 数组,整个使用 Cython 包装。
我可以让它返回vector<int>
而不是vector<int>&
,但我想了解使用引用时发生了什么。这是重现错误的一种方法:
CMYCLASS.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <vector>
#include <string>
namespace vec {
class IntVector {
private:
std::vector<int> vec;
public:
IntVector();
virtual ~IntVector();
std::vector<int>& get_vec(); #return a reference !
};
}
#endif
cmyclass.cc
#include "cmyclass.h"
#include <iostream>
using namespace vec;
IntVector::IntVector(){
for(int i=10; i<20; ++i){
vec.push_back(i);
}
}
IntVector::~IntVector(){
}
std::vector<int>& IntVector::get_vec(){
std::vector<int> buff;
buff.reserve(vec.size());
for(int i=0; i<vec.size(); ++i){
buff.push_back(vec[i]);
}
return buff;
}
myclass.pyx
import numpy as np
cimport numpy as np
from libcpp.vector cimport vector
cdef extern from "cmyclass.h" namespace "vec":
cdef cppclass IntVector:
IntVector() except +
vector[int]& get_vec()
cdef class IntVec:
cdef IntVector* _thisptr
def __cinit__(self):
self._thisptr = new IntVector()
def __dealloc__(self):
del self._thisptr
def __init__(self):
pass
def get_vec(self):
cdef vector[int] buff;
buff = self._thisptr.get_vec();
return np.asarray(buff)
setup.py
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
sourcefiles = ['myclass.pyx', 'cmyclass.cc']
compile_opts = ['-std=c++11']
ext=[Extension('*',
sourcefiles,
extra_compile_args=compile_opts,
language='c++')]
setup(
ext_modules=cythonize(ext)
)
您可以使用python setup.py build_ext --inplace
进行编译
用例
>>> import myclass
>>> vec = myclass.IntVec()
>>> vec.get_vec()
array([ 0, 0, 12, 13, 14, 15, 16, 17, 18, 19])
您可以看到前两个值设置为零(它们应该是 10 和 11(!如果我们返回一个vector<int>
而不是对vector<int>
的引用,代码将正常工作。
知道为什么会这样吗?
编辑:最终解决方案
将向量作为参数传递。
CMYCLASS.h
#ifndef MYCLASS_H
#define MYCLASS_H
#include <vector>
#include <string>
namespace vec {
class IntVector {
private:
std::vector<int> vec;
public:
IntVector();
virtual ~IntVector();
void get_vec(std::vector<int>&);
};
}
#endif
cmyclass.cc
#include "cmyclass.h"
#include <iostream>
using namespace vec;
IntVector::IntVector(){
for(int i=10; i<20; ++i){
vec.push_back(i);
}
}
IntVector::~IntVector(){
}
void IntVector::get_vec(std::vector<int>& buff){
buff.reserve(vec.size());
for(int i=0; i<vec.size(); ++i){
buff.push_back(vec[i]);
}
return buff;
}
myclass.pyx
import numpy as np
cimport numpy as np
from libcpp.vector cimport vector
cdef extern from "cmyclass.h" namespace "vec":
cdef cppclass IntVector:
IntVector() except +
void get_vec(vector[int]&)
cdef class IntVec:
cdef IntVector* _thisptr
def __cinit__(self):
self._thisptr = new IntVector()
def __dealloc__(self):
del self._thisptr
def __init__(self):
pass
def get_vec(self):
cdef vector[int] buff;
self._thisptr.get_vec(buff);
return np.asarray(buff)
setup.py
from distutils.core import setup
from Cython.Build import cythonize
from distutils.extension import Extension
sourcefiles = ['myclass.pyx', 'cmyclass.cc']
compile_opts = ['-std=c++11']
ext=[Extension('*',
sourcefiles,
extra_compile_args=compile_opts,
language='c++')]
setup(
ext_modules=cythonize(ext)
)
您的主要目标似乎是让 numpy 使用在C++向量中分配的内存。为此,您可能更好地实现IntVec
的缓冲区协议。Cython 文档提供了一个基于向量的矩阵类示例,您可以简化该向量(因为您的情况只有 1D(。您真正需要做的就是创建函数__getbuffer__
和__releasebuffer__
(后者可以是空白的,如示例文档中所示(。(我认为在这里复制/粘贴文档没有巨大的价值(
这样做将允许您将IntVec
直接传递给np.asarray
。生成的 numpy 数组将使用IntVec
进行存储,并保留对IntVec
的引用,以确保不会删除它。你也可以在此类中使用 Cython memoryviews(如果这有帮助的话(。
相关文章:
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 高级选择排序 - 在一次迭代中搜索两个元素
- 如何仅考虑 *指针中的前两个元素
- 为什么具有两个元素的发起器语法将一个元素而不是两个元素放入字符串向量中?
- 是否可以交换在 c++ 中作为函数 func(say) 中的参数传递的 const 向量的两个元素,例如:vector<int>func (const vector<int>&
- C++ std::向量插入两个元素替代算法失败
- 数组中两个元素的最大异或
- 我无法将二维数组的两个元素的差异分配给C++中其他数组的元素?
- 一个数组可以划分的最大子数组,使得不同子数组中任意两个元素的 GCD 始终为 1?
- 找到两个相关索引,其中两个元素等于目标值
- C++ - 前两个元素之间的差异
- C :交换两个不同向量的两个元素
- C 查找两个元素中出现的次数的数量
- 如何连接向量的两个元素
- 使用STL仅对两个元素进行排序
- 使用STL交换静态数组中的两个元素
- OpenGL:在两个元素之间画一条线
- C++矢量迭代器:比较和擦除两个元素
- 试图将字符串的两个元素组合在一起会得到错误的结果(c++)
- 由 8 个或更多位置分隔的数组中两个元素的最大乘积