问题
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