1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
/*
* SPDX-FileCopyrightText: All Contributors to the PyTango project
*
* SPDX-License-Identifier: LGPL-3.0-or-later
*/
#pragma once
#include "common_header.h"
#include "function_call_macros.h"
#include "convertors/vector_wrappers.h"
class DeviceClassTrampoline : public Tango::DeviceClass {
public:
DeviceClassTrampoline(const std::string &new_name) :
Tango::DeviceClass(const_cast<std::string &>(new_name)) { }
~DeviceClassTrampoline() override = default;
/**
* Export a device.
* Associate the servant to a CORBA object and send device network parameter
* to TANGO database.
* The main parameter sent to database is the CORBA object stringified device IOR.
*
* @param[in] dev The device to be exported (CORBA servant)
* @param[in] corba_dev_name The name to be used in the CORBA object key.
* This parameter does not need to be set in most of
* cases and has a default value. It is used for special
* device server like the database device server.
*/
void export_device(Tango::DeviceImpl *dev, const char *corba_dev_nam = "Unused") {
Tango::DeviceClass::export_device(dev, corba_dev_nam);
}
/**
* Creates an attribute and adds it to the att_list.
* This method is intended to be called by python to register a new
* attribute.
*/
void create_attribute(std::vector<Tango::Attr *> &att_list,
const std::string &attr_name,
Tango::CmdArgType attr_type,
Tango::AttrDataFormat attr_format,
Tango::AttrWriteType attr_write,
long dim_x,
long dim_y,
Tango::DispLevel display_level,
long polling_period,
bool memorized,
bool hw_memorized,
bool alarm_event_implemented,
bool alarm_event_detect,
bool archive_event_implemented,
bool archive_event_detect,
bool change_event_implemented,
bool change_event_detect,
bool data_ready_event_implemented,
const std::string &read_method_name,
const std::string &write_method_name,
const std::string &is_allowed_name,
Tango::UserDefaultAttrProp *att_prop);
void create_fwd_attribute(std::vector<Tango::Attr *> &att_list,
const std::string &attr_name,
Tango::UserDefaultFwdAttrProp *att_prop);
/**
* Creates a command.
* This method is intended to be called by python to register a new
* command.
*/
void create_command(const std::string &cmd_name,
Tango::CmdArgType param_type,
Tango::CmdArgType result_type,
const std::string ¶m_desc,
const std::string &result_desc,
Tango::DispLevel display_level,
bool default_command,
long polling_period,
const std::string &is_allowed);
/**
* This method forward a C++ call to the device_factory method to the
* Python method
*
* @param[in] dev_list The device name list
*/
void device_factory(const Tango::DevVarStringArray *dev_list) override {
CALL_PURE_VOID_METHOD(device_factory,
dev_list);
}
/**
* This method forward a C++ call to the attribute_factory method to the
* Python method
*
* @param[in] att_list attribute list
*
* Note! Due to pybind11 does not allow to bind vectors of raw pointers in a way,
* that they will be directly manipulated in Python.
* We do here some trick, and sending to python not a list but a wrapper.
* However, functionally in Python is not guaranteed!
*/
void attribute_factory(std::vector<Tango::Attr *> &att_list) override {
py::gil_scoped_acquire gil; // Ensure GIL is acquired
py::function override = py::get_override(this, "_attribute_factory");
if(override) {
try {
auto py_attr_list = std::make_shared<VectorWrapper<Tango::Attr>>(&att_list);
override(py_attr_list);
attr_vector_wrapper = py_attr_list;
}
CATCH_PY_EXCEPTION
} else {
Tango::DeviceClass::attribute_factory(att_list);
}
}
/**
* This method forward a C++ call to the pipe_factory method to the
* Python method
*
* @param[in] pipe_list pipe list
*/
void pipe_factory() override { }
/**
* This method forward a C++ call to the command_factory method to the
* Python method
*/
void command_factory() override {
CALL_PURE_VOID_METHOD(_command_factory, );
}
/**
* This method forward a C++ call to the device_name_factory method to the
* Python method
*/
void device_name_factory(StdStringVector &dev_list) override {
CALL_VOID_METHOD(device_name_factory,
Tango::DeviceClass,
dev_list)
}
/**
* This method forward a C++ call to the signal_handler method to the
* Python method or executes default signal handler if no signal handler
* is defined in python
*
* @param[in] signo signal identifier
*/
void signal_handler(long signo) override {
CALL_VOID_METHOD(signal_handler,
Tango::DeviceClass,
signo)
}
private:
/* Keep the wrappers alive
*
* NOTE: We do it to provide opportunity of manipulating these cpp vectors from Python code
* However, this is a potential source of both SEGFAULTS and memory leaks simultaneously....
*/
std::shared_ptr<VectorWrapper<Tango::Attr>> attr_vector_wrapper;
};
|