У меня есть иерархия C ++, которую мне нужно отразить в python. Базовый класс состоит из пары статических функций, ряда чисто виртуальных функций и ряда простых общедоступных функций с реализациями по умолчанию. Многие из этих методов могут использовать неконстантные ссылки для возврата значений в списке параметров. Реализуя это питоническим способом, я хотел бы вернуть те же значения, что и кортеж. Возможно ли это?
Этот вопрос очень похож на нерешенный вопрос
Ускорение Python, оборачивающее виртуальный метод , за исключением того, что рассматриваемые функции являются чисто виртуальными и изменяют как параметры, так и возвращаемые значения.
class Driver_comm
{
public:
Driver_comm() {};
virtual ~Driver_comm() {};
// -------------------------------------------------------------------------
virtual bool Enumerate_devices(const uint32_t vendor_id,
uint32_t &n_devices,
std::string &details) = 0;
};
class Driver_sim : public Driver_comm
{
public:
Driver_sim() {}
~Driver_sim() {}
// -------------------------------------------------------------------------
Driver_sim(const Driver_sim& r) = delete;
// -------------------------------------------------------------------------
const Driver_sim& operator=(const Driver_sim& r) = delete;
// -------------------------------------------------------------------------
bool Enumerate_devices(const uint32_t,
uint32_t &n_devices,
std::string &) override {
n_devices = 1; return true;
}
};
// ============================================================================
using namespace boost::python;
BOOST_PYTHON_MODULE(example)
{
struct Comm_wrapper : public Driver_comm, public wrapper<Driver_comm>
{
tuple enumerate_devices(const uint32_t vendor_id)
{
uint32_t n_devices;
std::string details;
bool ok = false;
override f_enumerate = this->get_override("Enumerate_devices");
if (f_enumerate)
{
ok = f_enumerate(vendor_id, n_devices, details);
}
else
{
printf("override = None");
}
return make_tuple(ok, n_devices, details.c_str());
}
};
class_<Comm_wrapper, boost::noncopyable>("driver_comm", no_init)
.def("Enumerate_devices", (&Comm_wrapper::enumerate_devices))
;
class_<Driver_sim, boost::noncopyable, bases<Driver_comm> >("driver_sim", init<>())
;
}
Звонок
n_devices = 0
result = ""
ok, n_devices, result = d.Enumerate_devices(0x1010)
приводит к ошибке "не соответствует сигнатуре C ++".
Python argument types in driver_comm.Enumerate_devices(driver_sim, int)
did not match C++ signature:
Enumerate_devices(struct `void __cdecl init_module_example(void)'::`2'::Comm
_wrapper {lvalue}, unsigned int)
При добавлении реализации по умолчанию к оболочке, как предложено в *, 1015 * не удается создать из-за несоответствия типа функции:
error C2664: 'void boost::python::detail::error::not_a_derived_class_member<Default>(Default)' : cannot convert argument 1 from 'bool (__cdecl Driver_comm::* )(uint32_t,uint32_t &,std::string &)' to 'boost::python::tuple (__cdecl init_module_example::Comm_wrapper::* )(uint32_t)'
Любое объяснение приветствуется. Если бы у pybind11 (или другого инструмента) был лучший способ решить эту проблему, я был бы рад развлечь его.