Cython и конструкторы классов

У меня проблема с использованием Cython конструкторов по умолчанию.

Мой класс C ++ Node следующий

Node.h

class Node
{
public:
Node()
{
std::cerr << "calling no arg constructor" << std::endl;
w=0.0;
d=0.0;
}
Node(double val, double val2);
{
std::cerr << "calling 2 args constructor" << std::endl;
this->w=val;
this->d=val2;
}
private:
double d,w;
}

завернут в Cython следующим образом

cdef extern from "Node.h":
cdef cppclass Node:
Node() except +
Node(double val1, double val2) except +
double d
double w

cdef class pyNode:
cdef Node *thisptr      # hold a C++ instance which we're wrapping

def __cinit__(self):
self.thisptr = new Node()

def __cinit__(self, double val1, double val2):
self.thisptr = new Node(val1,val2)

def __dealloc__(self):
del self.thisptr

def __repr__(self):
return "d=%s w=%s" % (self.thisptr.w, self.thisptr.w )

Код Cython хорошо компилируется, но особенно при вызове из Python

from pyNode import pyNode as Node
n=Node(1.0,2.0)

Я получил ожидаемое calling 2 args constructor строка, но если я пытаюсь объявить объект Node из python, используя конструктор «no-arguments» (который должен быть правильно объявлен как __cinit__(self) Я не получаю вывод, это означает, что конструктор без аргументов не вызывается!

Как я могу явно назвать это из CInit метод обернутого класса?

1

Решение

Проблема в том, что вы не можете перегрузить __cinit__() так (как только cdef функции могут быть перегружены) — вместо этого, пусть он принимает значения по умолчанию, а затем вызывает нужную вещь по мере необходимости.

Редактировать: По сути, вам нужно реализовать эту функцию в большей степени, чем в обычном коде Python, вместо использования перегрузки:

def __cinit__(self, double val1=-1, double val2=-1):
if val1 == -1 or val2 == -1:
self.thisptr = new Node()
else:
self.thisptr = new Node(val1,val2)

Естественно, это предполагает -1 это значение, которое бесполезно для функции, вы можете использовать другое значение, или если вам нужно, чтобы каждое значение типа double было допустимым, тогда вам может потребоваться удалить типизацию, взяв объект Python, чтобы вы могли использовать None по умолчанию:

def __cinit__(self, val1=None, val2=None):
if val1 is not None and val2 is not None:
self.thisptr = new Node(val1, val2)
else:
self.thisptr = new Node()
7

Другие решения

Других решений пока нет …