Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.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
做一个C++;类看起来像使用swig的numpy数组 什么是一个公开C++类的好方法,它提供了一个与NoPy(SIPY)?一起使用的数组式接口?_C++_Python_Numpy_Swig - Fatal编程技术网

做一个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);
    }
};
限制条件:

  • 我只关心将底层数据存储为连续平面阵列的类
  • 该类将提供对原始存储的公共访问(可能通过函数)
  • 我不能将Python特定代码添加到C++头文件/源文件(我们不需要) 对C++代码有一个Python依赖性,因此对C++有任何修改 必须通过SWIG(例如,
    %extend
    )进行侧边操作
我目前的方法是在SWIG
.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操作中使用它。)

我可以想象两种方法来改善这一点:

  • 向c类添加(通过SWIG
    %extend
    )附加功能,或
  • 让python函数返回数组切片代理对象
  • 我的主要障碍是不知道一个对象需要(有效地)实现什么接口才能像numpy数组一样嘎嘎作响

    测试用例

    以下是我的测试设置:

    //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);
    }