【问题标题】:Cython "Cannot take address of memoryview slice"Cython“无法获取 memoryview 切片的地址”
【发布时间】:2020-05-27 13:26:33
【问题描述】:

我无法在 Cython 中创建一个简单的类。在 C++ 包装器中处理数组的内存视图相关的文档很少。我想创建一个具有时间、x、y 和 z 属性的数据类。我需要这些属性是数组,最终可以在 Python 中调用。我以前使用 numpy 类型进行此工作,但我想使用 memoryviews 正确执行此操作。我的C++背景不强。目前,我只是想让 time 属性与单元素一维数组一起使用。当我尝试构建我的扩展时,我收到以下错误:

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


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

如果我无法获取 memoryview 切片的地址,我该如何初始化我的类属性?这是相关代码。

数据.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

数据.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 memoryviews 的类有任何见解,将不胜感激。

【问题讨论】:

  • 既然您在your last question 中提到它作为假设:您是否打算将date 参数的长度硬编码为单个long 的数组,或者您是否尝试支持任意长度的数组?如果您在 c++ 代码的构造函数中使用long *,您知道long * 指向的项目数吗?
  • 明天会在不那么累的时候写一个更有凝聚力的答案,但是由于您的 @property 函数只是简单的变量获取器和设置器,您可以查看将 cdef class Date 中的属性声明为 public (如果您希望它们不能从 python 端修改但仍然暴露,您可以查看readonly)。
  • 感谢您的帮助。对于日期,它可能是一个长度为 1 的数组,但我希望可以选择它是可扩展的。对于剩余的数组,它们都将是动态 3D 或 4D 数组(或向量的向量)。我希望它们可以从 Python 端修改,所以我会考虑将它们设置为 public。
  • 所以没有。 x、y 和 z 实际上每个都是 3 维数组(最少)。我的实际代码有 u、v 和 w,它们代表 3D 网格中的速度。我只是想在我的例子中简化一些事情,并且只考虑我的问题的一维时间。但是,是的,我的目标是最终为这些变量中的每一个提供多维数组。我希望我可以在 C++ 端实例化 3D 数组,但如果我愿意,可以选择从 Python 访问它们。所以我的数组将是 u、v、w 的三维数组,尺寸为 x、y、z(至少,可能是时间暗淡)。
  • 理想情况下,数组将从 netcdf 文件传递​​到 C++ 数组,其中包含所有 3D 数组的 C++ 类实例,因此我可以对它们执行进一步的操作,例如插值。

标签: python c++ arrays cython memoryview


【解决方案1】:

我不能说我完全理解我所做的事情,但是在回到我遵循的原始指导之后,我能够让它发挥作用。我收到的指导是来自https://www.youtube.com/watch?v=6ukI-NlIzqY 的视频和可以从https://github.com/kwmsmith/scipy2013-cython-tutorial/blob/master/Cython.pdf 观看的随附幻灯片。

这里是相关文件。

数据.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

数据.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 +

数据外部.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

数据外部.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 () {}

【讨论】:

    猜你喜欢
    • 2015-01-06
    • 1970-01-01
    • 2014-11-10
    • 2019-05-18
    • 2016-09-07
    • 1970-01-01
    • 1970-01-01
    • 2019-06-21
    • 2012-09-29
    相关资源
    最近更新 更多