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