Cython “Cannot take address of memoryview slice”

狂风中的少年 提交于 2020-02-25 06:05:07

问题


I am having trouble creating a simple class in Cython. There is little documentation related to handling memoryviews for arrays in C++ wrappers. I want to create a data class with time, x, y, and z attributes. I need these attributes to be arrays, which will ultimately be callable in Python. I previously had this working using numpy types, but I would like to do this properly using memoryviews. My background is not strong in C++. For now, I am only trying to get the time attribute working with a single-element 1D array. When I try to build my extensions I get the following error:

        self.c_data = new _Data(&date[1], x, y, z)
                               ^
------------------------------------------------------------


data.pyx:18:32: Cannot take address of memoryview slice

If I can't take the address of a memoryview slice, how do I initialize my class attributes? Here is the relevant code.

data.pyx

# distutils: language = c++

import numpy as np
cimport numpy as np
from cython.view cimport array as cvarray
from . cimport Data


cdef class Data:

    cdef _Data *c_data
    cdef long[::1] date

    def __cinit__(self, long[::1] *date, x, y, z):


        self.c_data = new _Data(&date[1], *date, x, y, z)
        self.date = cvarray(shape=(1), itemsize=sizeof(long), format="i")


    def __dealloc__(self):
        del self.c_data

data.pxd

cdef extern from "data extern.cpp":
    pass

cdef extern from "data extern.h":

    cppclass _Data "Data":

        long date[1]
        double x, y, z
        Data() except +
        _Data(long[:], double, double, double) except +

data_extern.h

#ifndef DATA_EXTERN_H
#define DATA_EXTERN_H

class Data {
    public:
        long date[1];
        double x, y, z;
        Data();
        Data(long date[1], double x, double y, double z);
        ~Data();

};

#endif

data_extern.cpp

#include <iostream>
#include "data extern.h"

// Default constructor
Data::Data () {}

// Overloaded constructor
Data::Data (long date[1], double x, double y, double z) {
    this->date = date[0];
    this->x = x;
    this->y = y;
    this->z = z;
}

// Destructor
Data::~Data () {}

There are likely other issues with my code. If anybody has any insights on how I can create a class that is callable from python and makes use of cython memoryviews, it would be greatly appreciated.


回答1:


I can't say I quite understand what I've done, but after going back to the original guidance I was following, I was able to get it to work. The guidance I received was a video from https://www.youtube.com/watch?v=6ukI-NlIzqY and the accompanying slides that can be viewed from https://github.com/kwmsmith/scipy2013-cython-tutorial/blob/master/Cython.pdf.

Here are the relevant files.

data.pyx

# distutils: language = c++

cdef class Data:

    cdef _Data *c_data
    cdef long[::1] date

    def __cinit__(self, long[::1] date, x, y, z):
        self.c_data = new _Data(&date[0], x, y, z)

    def __dealloc__(self):
        del self.c_data

    @property
    def date(self):
        return self.c_data.date
    @date.setter
    def date(self, date):
        self.c_data.date = date

    @property
    def x(self):
        return self.c_data.x
    @x.setter
    def x(self, x):
        self.c_data.x = x

    @property
    def y(self):
        return self.c_data.y
    @y.setter
    def y(self, y):
        self.c_data.y = y

    @property
    def z(self):
        return self.c_data.z
    @z.setter
    def z(self, z):
        self.c_data.z = z

data.pxd

cdef extern from "data extern.cpp":
    pass

cdef extern from "data extern.h":

    cppclass _Data "Data":

        long date[1]
        double x, y, z
        Data() except +
        _Data(long*, double, double, double) except +

data extern.h

#ifndef DATA_EXTERN_H
#define DATA_EXTERN_H

class Data {
    public:
        long *date;
        double x, y, z;
        Data();
        Data(long date[1], double x, double y, double z);
        ~Data();

};

#endif

data extern.cpp

#include <iostream>
#include "data extern.h"

// Default constructor
Data::Data () {}

// Overloaded constructor
Data::Data (long *date, double x, double y, double z) {
    this->date = &date[0];
    this->x = x;
    this->y = y;
    this->z = z;
}

// Destructor
Data::~Data () {}


来源:https://stackoverflow.com/questions/60180703/cython-cannot-take-address-of-memoryview-slice

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!