Расширение виртуального класса C ++, предоставляемого через Boost.Python

Я пытаюсь выставить этот класс C ++, используя Boost.Python:

class VAlgorithm {
public:

VAlgorithm(const char *name);

virtual ~VAlgorithm();

virtual bool Initialize() = 0;
virtual bool Process() = 0;
virtual bool Finalize() = 0;

virtual const char *GetName() const; // Default implementation in cpp file
}

Моя конечная цель — определить дочерние элементы VAlgorithm в оболочке python как классы python. Следующий этот пример, Я определил класс обратного вызова:

class VAlgorithm_callback: public VAlgorithm {
public:
VAlgorithm_callback(PyObject *p, const char *name) :
self(p), VAlgorithm(name) {
}
const char * GetName() const {
return call_method<const char *>(self, "GetName");
}

static const char * GetName_default(const VAlgorithm& self_) {
return self_.VAlgorithm::GetName();
}

private:
PyObject *self;
};

Прямо сейчас я выставляю только сам класс и метод GetName (). Поскольку это виртуальный класс, я поместил этот код в BOOST_PYTHON_MODULE:

class_<VAlgorithm, VAlgorithm_callback, boost::noncopyable>("VAlgorithm", no_init) //
.def("GetName", &VAlgorithm_callback::GetName_default); //

Я могу скомпилировать это и загрузить модуль в оболочку Python. Затем я пытаюсь определить дочерний класс и вызвать реализацию по умолчанию GetName (), определенную в коде C ++:

>>> class ConcAlg1(VAlgorithm):
...   pass
...
>>> c1 = ConcAlg1("c1")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
RuntimeError: This class cannot be instantiated from Python
>>> class ConcAlg2(VAlgorithm):
...   def __init__(self, name):
...     pass
...
>>> c2 = ConcAlg2("c2")
>>> c2.GetName()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
Boost.Python.ArgumentError: Python argument types in
VAlgorithm.GetName(ConcAlg2)
did not match C++ signature:
GetName(VAlgorithm)
>>> class ConcAlg3(VAlgorithm):
...   def __init__(self, name):
...     super(ConcAlg3, self).__init__(self, name)
...
>>> c3 = ConcAlg3("c3")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 3, in __init__
RuntimeError: This class cannot be instantiated from Python

Я не эксперт (просто сталкиваюсь с этими проблемами в первый раз), но мне кажется, что ConcAlg1 и ConcAlg3 пытаются создать экземпляр объекта VAlgorithm и дают сбой из-за параметра no_init, используемого при раскрытии VAlgorithm (я не могу его опустить или код не скомпилируется), и ConcAlg2 не может вызвать GetName (), потому что каким-то образом он не распознается как дочерний элемент VAlgorithm.
Я должен делать что-то тривиально неправильно, но я не могу понять, что (я новичок в Boost.Python и расширения). Кто-нибудь может мне помочь, пожалуйста! Спасибо

1

Решение

Я сделал вещи, очень похожие на это. Почему бы вам не следовать тому, что вы уже нашли в своем комментарии?

Когда вы создаете экземпляр класса, производного от VAlgorithm в Python, VAlgorithm_callback должен быть создан в C ++ для его представления. Это невозможно, если вы не объявляете конструктор в BOOST_PYTHON_MODULE.

То, как это делается в примере, должно быть в порядке:

class_<VAlgorithm, VAlgorithm_callback, boost::noncopyable>("VAlgorithm", init<std::string>())

Когда вы определяете в этом дочернего класса, вы можете использовать следующий синтаксис для вызова родительского конструктора (но ваш код тоже может работать, это просто так, как я). В примере, который вы использовали, они даже не определяют в этом поэтому вместо него вызывается родительский.

class ConcAlg3(VAlgorithm):
def __init__(self, name):
VAlgorithm.__init__(self, name)
0

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

Я думаю, что нашел решение. Проходя через пример, который я цитировал в моем запросе, а также документацию поддержки Вот, Я понял, что проблема в том, что класс обратного вызова является реальным классом, заключенным в Boost.Python, и что это должен быть конкретный класс. Итак, я реализовал в нем недостающие чисто виртуальные методы:

class VAlgorithm_callback: public VAlgorithm {
public:
VAlgorithm_callback(PyObject *p, const char *name) :
self(p), VAlgorithm(name) {
}

virtual bool Initialize() {
return call_method<bool>(self, "Initialize");
}
virtual bool Process() {
return call_method<bool>(self, "Process");
}
virtual bool Finalize() {
return call_method<bool>(self, "Finalize");
}

const char * GetName() const {
return call_method<const char *>(self, "GetName");
}

// Supplies the default implementation of GetName
static const char * GetName_default(const VAlgorithm& self_) {
return self_.VAlgorithm::GetName();
}

private:
PyObject *self;
};

а также изменил оболочку как:

class_<VAlgorithm, boost::shared_ptr<VAlgorithm_callback>, boost::noncopyable ("VAlgorithm", init<const char *>()) //
.def("Initialize", &VAlgorithm_callback::Initialize)
.def("Process", &VAlgorithm_callback::Process)
.def("Finalize", &VAlgorithm_callback::Finalize)
.def("GetName", &VAlgorithm_callback::GetName_default);

Теперь я могу определить дочерний класс в Python и вызвать метод GetName () по умолчанию:

>>> class ConcAlg(VAlgorithm):
...   pass
...
>>> c = ConcAlg("c")
>>> c.GetName()
'c'
>>>
0

По вопросам рекламы [email protected]