GNU Radio Manual and C++ API Reference  3.9.8.0
The Free & Open Software Radio Ecosystem
pycallback_object.h
Go to the documentation of this file.
1 /* -*- c++ -*- */
2 /*
3  * Copyright 2012 Free Software Foundation, Inc.
4  *
5  * This file is part of GNU Radio
6  *
7  * SPDX-License-Identifier: GPL-3.0-or-later
8  *
9  */
10 
12 #include <pythread.h>
13 #include <boost/format.hpp>
14 #include <iostream>
15 
16 #include <iostream>
17 
19 
21 
22 // a simple to-PMT converter template class-function
23 template <class myType>
25 {
26 public:
27  static pmt::pmt_t make(myType _val) { return pmt::mp(_val); }
28 };
29 
30 /* template specializations for vectors that can't use pmt::mp() */
31 template <>
32 pmt::pmt_t pmt_assist<std::vector<float>>::make(std::vector<float> _val)
33 {
34  return pmt::init_f32vector(_val.size(), _val);
35 }
36 
37 template <>
38 pmt::pmt_t pmt_assist<std::vector<gr_complex>>::make(std::vector<gr_complex> _val)
39 {
40  return pmt::init_c32vector(_val.size(), _val);
41 }
42 
43 template <class myType>
45 {
46 public:
47  pycallback_object(std::string name,
48  std::string functionbase,
49  std::string units,
50  std::string desc,
51  myType min,
52  myType max,
53  myType deflt,
54  DisplayType dtype)
55  : d_callback(NULL),
56  d_functionbase(functionbase),
57  d_units(units),
58  d_desc(desc),
59  d_min(min),
60  d_max(max),
61  d_deflt(deflt),
62  d_dtype(dtype),
63  d_name(name),
65  {
66  d_callback = NULL;
67  setup_rpc();
68  }
69 
70  void add_rpc_variable(rpcbasic_sptr s) { d_rpc_vars.push_back(s); }
71 
72  myType get()
73  {
74  myType rVal = d_deflt;
75  if (d_callback == NULL) {
76  std::cerr
77  << "WARNING: pycallback_object get() called without py callback set!"
78  << std::endl;
79  return rVal;
80  } else {
81  // obtain PyGIL
82  PyGILState_STATE state = PyGILState_Ensure();
83 
84  PyObject* func;
85  // PyObject *arglist;
86  PyObject* result;
87 
88  func = (PyObject*)d_callback; // Get Python function
89  // arglist = Py_BuildValue(""); // Build argument list
90  result = PyEval_CallObject(func, NULL); // Call Python
91  // result = PyEval_CallObject(func,arglist); // Call Python
92  // Py_DECREF(arglist); // Trash arglist
93  if (result) { // If no errors, return double
94  rVal = pyCast(result);
95  }
96  Py_XDECREF(result);
97 
98  // release PyGIL
99  PyGILState_Release(state);
100  return rVal;
101  }
102  }
103 
104  void set_callback(PyObject* cb) { d_callback = cb; }
105 
106  void setup_rpc()
107  {
108 #ifdef GR_CTRLPORT
111  (boost::format("%s%d") % d_name % d_id).str(),
112  d_functionbase.c_str(),
113  this,
117  pmt_assist<myType>::make(d_deflt),
118  d_units.c_str(),
119  d_desc.c_str(),
121  d_dtype)));
122 #endif /* GR_CTRLPORT */
123  }
124 
125 private:
126  PyObject* d_callback;
127  std::string d_functionbase, d_units, d_desc;
128  myType d_min, d_max, d_deflt;
129  DisplayType d_dtype;
130 
131  /* This is a fall-through converter in case someone tries to call pyCast on an
132  * object type for which there isn't a template specialization (located below
133  * this class) function. This function should never get called, and it is
134  * unknown if changing the return type from myType to 'void' will break
135  * something. */
136  myType pyCast(PyObject* obj)
137  {
138  std::cerr << "TYPE NOT IMPLEMENTED!" << std::endl;
139  assert(0);
140  // the following is to make compilers happy only.
141  myType dummy;
142  return (dummy);
143  };
144 
145  std::vector<rpcbasic_sptr> d_rpc_vars; // container for all RPC variables
146  std::string d_name;
147  int d_id;
148 };
149 
150 
151 // template specialization conversion functions
152 // get data out of the PyObject and into the real world
153 template <>
154 std::string pycallback_object<std::string>::pyCast(PyObject* obj)
155 {
156 #if PY_MAJOR_VERSION >= 3
157  return std::string(PyUnicode_AsUTF8(obj));
158 #else
159  return std::string(PyString_AsString(obj));
160 #endif
161 }
162 
163 template <>
164 double pycallback_object<double>::pyCast(PyObject* obj)
165 {
166  return PyFloat_AsDouble(obj);
167 }
168 
169 template <>
170 float pycallback_object<float>::pyCast(PyObject* obj)
171 {
172  return (float)PyFloat_AsDouble(obj);
173 }
174 
175 template <>
176 int pycallback_object<int>::pyCast(PyObject* obj)
177 {
178  return PyInt_AsLong(obj);
179 }
180 
181 template <>
182 std::vector<float> pycallback_object<std::vector<float>>::pyCast(PyObject* obj)
183 {
184  int size = PyObject_Size(obj);
185  std::vector<float> rval(size);
186  for (int i = 0; i < size; i++) {
187  rval[i] = (float)PyFloat_AsDouble(PyList_GetItem(obj, i));
188  }
189  return rval;
190 }
191 
192 template <>
193 std::vector<gr_complex> pycallback_object<std::vector<gr_complex>>::pyCast(PyObject* obj)
194 {
195  int size = PyObject_Size(obj);
196  std::vector<gr_complex> rval(size);
197  for (int i = 0; i < size; i++) {
198  rval[i] = gr_complex((float)PyComplex_RealAsDouble(PyList_GetItem(obj, i)),
199  (float)PyComplex_ImagAsDouble(PyList_GetItem(obj, i)));
200  }
201  return rval;
202 }
203 // TODO: add more template specializations as needed!
Definition: pycallback_object.h:18
pycallback_object(std::string name, std::string functionbase, std::string units, std::string desc, myType min, myType max, myType deflt, DisplayType dtype)
Definition: pycallback_object.h:47
float min(float a, float b)
int pycallback_object_count
Definition: pycallback_object.h:20
void setup_rpc()
Definition: pycallback_object.h:106
static pmt::pmt_t make(myType _val)
Definition: pycallback_object.h:27
pyport_t
Definition: pycallback_object.h:18
Definition: rpccallbackregister_base.h:34
Definition: pycallback_object.h:44
Registers a &#39;get&#39; function to get a parameter over ControlPort.
Definition: rpcregisterhelpers.h:1106
std::complex< float > gr_complex
Definition: gr_complex.h:15
void set_callback(PyObject *cb)
Definition: pycallback_object.h:104
PMT_API pmt_t init_f32vector(size_t k, const float *data)
PMT_API pmt_t init_c32vector(size_t k, const std::complex< float > *data)
Definition: pycallback_object.h:18
void add_rpc_variable(rpcbasic_sptr s)
Definition: pycallback_object.h:70
Definition: pycallback_object.h:24
static pmt_t mp(const std::string &s)
Make pmt symbol.
Definition: pmt_sugar.h:24
myType get()
Definition: pycallback_object.h:72
std::shared_ptr< pmt_base > pmt_t
typedef for shared pointer (transparent reference counting).
Definition: pmt.h:84
uint32_t DisplayType
Definition: rpccallbackregister_base.h:17