GNU Radio Manual and C++ API Reference  3.8.1.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  * GNU Radio is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 3, or (at your option)
10  * any later version.
11  *
12  * GNU Radio is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with GNU Radio; see the file COPYING. If not, write to
19  * the Free Software Foundation, Inc., 51 Franklin Street,
20  * Boston, MA 02110-1301, USA.
21  */
22 
24 #include <pythread.h>
25 #include <boost/format.hpp>
26 #include <iostream>
27 
29 
31 
32 // a simple to-PMT converter template class-function
33 template <class myType>
35 {
36 public:
37  static pmt::pmt_t make(myType _val) { return pmt::mp(_val); }
38 };
39 
40 /* template specializations for vectors that can't use pmt::mp() */
41 template <>
43 {
44  return pmt::init_f32vector(_val.size(), _val);
45 }
46 
47 template <>
49 {
50  return pmt::init_c32vector(_val.size(), _val);
51 }
52 
53 template <class myType>
55 {
56 public:
57  pycallback_object(std::string name,
58  std::string functionbase,
59  std::string units,
60  std::string desc,
61  myType min,
62  myType max,
63  myType deflt,
64  DisplayType dtype)
65  : d_callback(NULL),
66  d_functionbase(functionbase),
67  d_units(units),
68  d_desc(desc),
69  d_min(min),
70  d_max(max),
71  d_deflt(deflt),
72  d_dtype(dtype),
73  d_name(name),
75  {
76  d_callback = NULL;
77  setup_rpc();
78  }
79 
80  void add_rpc_variable(rpcbasic_sptr s) { d_rpc_vars.push_back(s); }
81 
82  myType get()
83  {
84  myType rVal = d_deflt;
85  if (d_callback == NULL) {
86  printf("WARNING: pycallback_object get() called without py callback set!\n");
87  return rVal;
88  } else {
89  // obtain PyGIL
90  PyGILState_STATE state = PyGILState_Ensure();
91 
92  PyObject* func;
93  // PyObject *arglist;
94  PyObject* result;
95 
96  func = (PyObject*)d_callback; // Get Python function
97  // arglist = Py_BuildValue(""); // Build argument list
98  result = PyEval_CallObject(func, NULL); // Call Python
99  // result = PyEval_CallObject(func,arglist); // Call Python
100  // Py_DECREF(arglist); // Trash arglist
101  if (result) { // If no errors, return double
102  rVal = pyCast(result);
103  }
104  Py_XDECREF(result);
105 
106  // release PyGIL
107  PyGILState_Release(state);
108  return rVal;
109  }
110  }
111 
112  void set_callback(PyObject* cb) { d_callback = cb; }
113 
114  void setup_rpc()
115  {
116 #ifdef GR_CTRLPORT
117  add_rpc_variable(
119  (boost::format("%s%d") % d_name % d_id).str(),
120  d_functionbase.c_str(),
121  this,
125  pmt_assist<myType>::make(d_deflt),
126  d_units.c_str(),
127  d_desc.c_str(),
129  d_dtype)));
130 #endif /* GR_CTRLPORT */
131  }
132 
133 private:
134  PyObject* d_callback;
135  std::string d_functionbase, d_units, d_desc;
136  myType d_min, d_max, d_deflt;
137  DisplayType d_dtype;
138 
139  /* This is a fall-through converter in case someone tries to call pyCast on an
140  * object type for which there isn't a template specialization (located below
141  * this class) function. This function should never get called, and it is
142  * unknown if changing the return type from myType to 'void' will break
143  * something. */
144  myType pyCast(PyObject* obj)
145  {
146  printf("TYPE NOT IMPLEMENTED!\n");
147  assert(0);
148  // the following is to make compilers happy only.
149  myType dummy;
150  return (dummy);
151  };
152 
153  std::vector<rpcbasic_sptr> d_rpc_vars; // container for all RPC variables
154  std::string d_name;
155  int d_id;
156 };
157 
158 
159 // template specialization conversion functions
160 // get data out of the PyObject and into the real world
161 template <>
162 std::string pycallback_object<std::string>::pyCast(PyObject* obj)
163 {
164  return std::string(PyString_AsString(obj));
165 }
166 
167 template <>
168 double pycallback_object<double>::pyCast(PyObject* obj)
169 {
170  return PyFloat_AsDouble(obj);
171 }
172 
173 template <>
174 float pycallback_object<float>::pyCast(PyObject* obj)
175 {
176  return (float)PyFloat_AsDouble(obj);
177 }
178 
179 template <>
180 int pycallback_object<int>::pyCast(PyObject* obj)
181 {
182  return PyInt_AsLong(obj);
183 }
184 
185 template <>
186 std::vector<float> pycallback_object<std::vector<float>>::pyCast(PyObject* obj)
187 {
188  int size = PyObject_Size(obj);
189  std::vector<float> rval(size);
190  for (int i = 0; i < size; i++) {
191  rval[i] = (float)PyFloat_AsDouble(PyList_GetItem(obj, i));
192  }
193  return rval;
194 }
195 
196 template <>
197 std::vector<gr_complex> pycallback_object<std::vector<gr_complex>>::pyCast(PyObject* obj)
198 {
199  int size = PyObject_Size(obj);
200  std::vector<gr_complex> rval(size);
201  for (int i = 0; i < size; i++) {
202  rval[i] = gr_complex((float)PyComplex_RealAsDouble(PyList_GetItem(obj, i)),
203  (float)PyComplex_ImagAsDouble(PyList_GetItem(obj, i)));
204  }
205  return rval;
206 }
207 // TODO: add more template specializations as needed!
Definition: pycallback_object.h:28
boost::shared_ptr< pmt_base > pmt_t
typedef for shared pointer (transparent reference counting). See http://www.boost.org/libs/smart_ptr/smart_ptr.htm
Definition: pmt.h:96
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:57
float min(float a, float b)
int pycallback_object_count
Definition: pycallback_object.h:30
void setup_rpc()
Definition: pycallback_object.h:114
static pmt::pmt_t make(myType _val)
Definition: pycallback_object.h:37
pyport_t
Definition: pycallback_object.h:28
Definition: rpccallbackregister_base.h:46
Definition: pycallback_object.h:54
Registers a &#39;get&#39; function to get a parameter over ControlPort.
Definition: rpcregisterhelpers.h:1117
std::complex< float > gr_complex
Definition: gr_complex.h:27
void set_callback(PyObject *cb)
Definition: pycallback_object.h:112
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:28
void add_rpc_variable(rpcbasic_sptr s)
Definition: pycallback_object.h:80
Definition: pycallback_object.h:34
static pmt_t mp(const std::string &s)
Make pmt symbol.
Definition: pmt_sugar.h:35
myType get()
Definition: pycallback_object.h:82
uint32_t DisplayType
Definition: rpccallbackregister_base.h:29