Cython “Cannot assign default value to fields in cdef classes, structs or unions”

允我心安 提交于 2021-01-05 12:59:36

问题


I am making my first attempt at porting Python code to Cython. I only have very limited experience with C. I am trying to make a relatively simple class that stores multidimensional arrays. For the purpose of this question, let's leave it to a single one-dimensional array of length 1 for the attribute time. Currently, I am recieving the error:

    cdef np.ndarray[np.int64_t, ndim=1] time = np.empty([1], dtype=np.int64)
                                       ^
------------------------------------------------------------
data.pyx:22:40: Cannot assign default value to fields in cdef classes, structs or unions

Here are the most relevant files.

data.pyx

import numpy as np
cimport numpy as np


cdef extern from "data_extern.h":

    cppclass _Data "Data":

        np.int64_t time64[1]
        double x_coord, y_coord, z_coord
        _Data(np.int64_t *time, double x, double y, double z)


cdef class Data:

    cdef _Data *thisptr
    cdef np.ndarray[np.int64_t, ndim=1] time = np.empty([1], dtype=np.int64)

    def __cinit__(self, np.int64_t time[1], x, y, z):
        self.thisptr = new _Data(&time[0], x, y, z)

    def __dealloc__(self):
        del self.thisptr

data_extern.h

#ifndef DATA_EXTERN_H
#define DATA_EXTERN_H

class Data {
    public:
        signed long long time64[1];
        double x_coord, y_coord, z_coord;
        Data();
        Data(signed long long time[1], double x, double y, double z;
        ~Data();
};

#endif

data_extern.cpp

#include <iostream>
#include "data_extern.h"

Data::Data () {}

// Overloaded constructor
Data::Data (signed long long time[1], double x, double y, double z {
    this->time64 = time[0];
    this->x_coord = x;
    this->y_coord = y;
    this->z_coord = z;
}

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

I recognize there could be multiple problems with my code, but if someone could provide an explanation for the error message it would be much appreciated.


回答1:


The problem is as stated in the error message: you cannot set a default value for a cdef class's C-level properties. You can get around this by setting the value in the __cinit__ constructor as follows:

cdef class Data:
    cdef _Data *thisptr
    cdef np.ndarray[np.int64_t, ndim=1] time

    def __cinit__(self, np.int64_t time[1], x, y, z):
        self.thisptr = new _Data(&time[0], x, y, z)
        self.time = np.empty([1], dtype=np.int64)

    def __dealloc__(self):
        del self.thisptr

As a heads-up though, the whole np.ndarray syntax is rather out of date. Unless you are dead-set on using numpy types (which seem to be unnecessary in your code since you are interfacing with a c++ library of some sort), you can use the more modern typed memoryview syntax. You could import the sized integer types using from libc.stdint cimport * to use those instead of the numpy ones.



来源:https://stackoverflow.com/questions/60159909/cython-cannot-assign-default-value-to-fields-in-cdef-classes-structs-or-unions

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