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