File: device_class.h

package info (click to toggle)
pytango 10.1.4-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,304 kB
  • sloc: python: 27,795; cpp: 16,150; sql: 252; sh: 152; makefile: 43
file content (168 lines) | stat: -rw-r--r-- 6,275 bytes parent folder | download
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 &param_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;
};