Cython "Невозможно получить адрес среза памяти" - PullRequest
1 голос
/ 12 февраля 2020

У меня проблемы с созданием простого класса на Cython. Существует немного документации, связанной с обработкой представлений памяти для массивов в оболочках C ++. Я хочу создать класс данных с атрибутами time, x, y и z. Мне нужно, чтобы эти атрибуты были массивами, которые в конечном итоге будут вызываться в Python. Раньше у меня это работало с использованием numpy типов, но я хотел бы сделать это правильно, используя просмотры памяти. Мой опыт не очень силен в C ++. Пока я только пытаюсь заставить атрибут времени работать с одноэлементным 1D массивом. Когда я пытаюсь построить свои расширения, я получаю следующую ошибку:

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


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

Если я не могу получить адрес среза памяти, как я могу инициализировать свои атрибуты класса? Вот соответствующий код.

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 () {}

Вероятно, есть другие проблемы с моим кодом. Если у кого-нибудь есть понимание того, как я могу создать класс, который можно вызывать из python и который использует представления памяти cython, это было бы очень полезно.

1 Ответ

0 голосов
/ 13 февраля 2020

Не могу сказать, что вполне понимаю, что я сделал, но вернувшись к первоначальному руководству, которому я следовал, я смог заставить его работать. Руководство, которое я получил, было видео с https://www.youtube.com/watch?v=6ukI-NlIzqY и сопутствующими слайдами, которые можно просмотреть с https://github.com/kwmsmith/scipy2013-cython-tutorial/blob/master/Cython.pdf.

Вот соответствующие файлы.

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 () {}
...