做一个C++;类看起来像使用swig的numpy数组 什么是一个公开C++类的好方法,它提供了一个与NoPy(SIPY)?一起使用的数组式接口?
所谓数组式接口,我指的是:做一个C++;类看起来像使用swig的numpy数组 什么是一个公开C++类的好方法,它提供了一个与NoPy(SIPY)?一起使用的数组式接口?,c++,python,numpy,swig,C++,Python,Numpy,Swig,所谓数组式接口,我指的是: //file:Arr.h class Arr{ public: int n_rows; int n_cols; float* m_data; Arr(int r, int c, float v); virtual ~Arr(); float get(int i, int j); void set(int i, int j, float v); long data_addr(){ ret
//file:Arr.h
class Arr{
public:
int n_rows;
int n_cols;
float* m_data;
Arr(int r, int c, float v);
virtual ~Arr();
float get(int i, int j);
void set(int i, int j, float v);
long data_addr(){
return (long)(m_data);
}
};
限制条件:
- 我只关心将底层数据存储为连续平面阵列的类
- 该类将提供对原始存储的公共访问(可能通过函数)
%extend
)进行侧边操作
.i
文件中放置一个pythoncode
块
看起来像
%pythoncode{
def arraylike_getitem(self, arg1,arg2 ):
# the actual implementation to handle slices
# is pretty complicated but involves:
# 1. constructing an uninitialized numpy array for return value
# 2. iterating over the indices indicated by the slices,
# 3. calling self.getValue for each of the index pairs,
# 4. returning the array
# add the function to the ArrayLike class
Arr.__getitem__=arraylike_getitem
%}
<> > <代码>数组类< /C> >是保存数字数据的C++类(作为平面数组),
并提供成员函数以获取/设置单个值
主要缺点是步骤1。上图:我必须复制任何切片
我从我的c-array类中获取。(主要优点是通过返回
numpy数组对象,我知道我可以在任何我想要的numpy操作中使用它。)
我可以想象两种方法来改善这一点:
%extend
)附加功能,或//file:Arr.h
class Arr{
public:
int n_rows;
int n_cols;
float* m_data;
Arr(int r, int c, float v);
virtual ~Arr();
float get(int i, int j);
void set(int i, int j, float v);
long data_addr(){
return (long)(m_data);
}
};
//-----------------------------------------------------------
//file Arr.cpp
#include "Arr.h"
Arr::Arr(int r, int c, float v): n_rows(r), n_cols(c), m_data(0){
m_data=new float[ r*c ];
for( int i=0; i<r*c; ++i){
m_data[i]=v;
}
}
Arr::~Arr(){
delete[] m_data;
}
float Arr::get(int i, int j){
return m_data[ i*n_cols+j];
}
void Arr::set(int i, int j, float v){
m_data[i*n_cols+j]=v;
}
//--------------------------------------------------------------------
//file:arr.i
%module arr
%{
#include "Arr.h"
#include </usr/lib64/python2.7/site-packages/numpy/core/include/numpy/ndarrayobject.h>
#include <python2.7/Python.h>
%}
%include "Arr.h"
%pythoncode{
# Partial solution (developed in constructing the question): allows operations between
# arr objects and numpy arrays (e.g. numpy_array+arr_object is OK)
# but does not allow slicing (e.g. numpy_array[::2,::2]+arr_objec[::2,::2])
# TODO: figure out how to get slices without copy memory
def arr_interface_map(self):
res={ 'shape':(self.n_rows, self.n_cols), 'typestr':'<f4', 'data': self.data_addr(),0), 'version':3 }
return res
Arr.__array_interface__=property( arr_interface_map )
}
//---------------------------------------------------------
#file: Makefile
INCLUDE_FLAGS = -I/usr/include/python2.7
arr_wrap.cpp: arr.i Arr.h
swig -c++ -python -o $@ ${INCLUDE_FLAGS} arr.i
_arr.so: arr_wrap.o Arr.o
g++ -shared -o _arr.so arr_wrap.o Arr.o
clean:
rm -f *.o *_wrap.cpp *.so
all: _arr.so
//文件:Arr.h
类Arr{
公众:
int n_行;
int n_cols;
浮点*m_数据;
Arr(整数r、整数c、浮点v);
虚拟~Arr();
浮点get(inti,intj);
无效集(int i,int j,float v);
长数据地址(){
返回(长)(m_数据);
}
};
//-----------------------------------------------------------
//文件Arr.cpp
#包括“Arr.h”
Arr::Arr(int r,int c,float v):n_行(r),n_列(c),m_数据(0){
m_data=新浮点数[r*c];
对于(int i=0;i如果n_cols
和n_行
是(有效地)不可变的,那么最好的做法是创建一个真正的numpy数组,将m_数据
作为存储和(n_行,n_cols)
as shape。这样,您就可以获得所有numpy阵列功能,而无需进行任何复制,也无需在您自己的代码中重新实现它们(这将是一个很大的模仿)
当然,这不会像写的那样起作用,因为您的m_数据
成员受到保护。但最好将其公开或提供访问器来检索它(或从ArrayLike
继承,并在您的子类中提供此类功能).对我不起作用:调用数组就像调用numpy
会导致分段错误。@Dave你能提供一个最小的可编译示例说明分段错误吗?如果没有它,很难猜测可能会出什么问题。我将你的方法视为“将上面的函数放入%{…%}”
literal在.i
文件中包含块,然后将该函数包装到swig文件的接口定义部分。@Dave我不熟悉swig的工作原理,所以我不知道这是否正确。但是,根据,我提供的简单函数应该将ArrayLike
转换为Python对象。事实上,您可以通过在程序中的某个地方添加诸如PyObject\u SetAttrString(PyImportImportModule(“sys”)、“my\u数组”、array\u like\u to\u numpy(*new ArrayLike())
之类的行来测试函数是否可以在没有SWIG的情况下工作。如果sys.my\u数组
作为numpy数组工作,则函数可以正常工作。
PyObject* array_like_to_numpy(ArrayLike& obj)
{
npy_intp dims[] = { obj.n_rows, obj.n_cols };
return PyArray_SimpleNewFromData(2, dims, NPY_FLOAT, obj.m_data);
}