GNU Radio Manual and C++ API Reference  3.7.9.2
The Free & Open Software Radio Ecosystem
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
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 
23 #include <iostream>
25 #include <pythread.h>
26 #include <boost/format.hpp>
27 
28 enum pyport_t {
31 };
32 
34 
35 // a simple to-PMT converter template class-function
36 template <class myType> class pmt_assist
37 {
38 public:
39  static pmt::pmt_t make(myType _val)
40  {
41  return pmt::mp(_val);
42  }
43 };
44 
45 /* template specializations for vectors that cant use pmt::mp() */
46 template<>
47 pmt::pmt_t pmt_assist<std::vector<float> >::make(std::vector<float> _val)
48 {
49  return pmt::init_f32vector(_val.size(), &_val[0]);
50 }
51 
52 template<>
53 pmt::pmt_t pmt_assist<std::vector<gr_complex> >::make(std::vector<gr_complex> _val)
54 {
55  return pmt::init_c32vector(_val.size(), &_val[0]);
56 }
57 
58 template <class myType> class pycallback_object
59 {
60 public:
61  pycallback_object(std::string name, std::string functionbase,
62  std::string units, std::string desc,
63  myType min, myType max, myType deflt,
64  DisplayType dtype) :
65  d_callback(NULL),
66  d_functionbase(functionbase), d_units(units), d_desc(desc),
67  d_min(min), d_max(max), d_deflt(deflt), d_dtype(dtype),
68  d_name(name), d_id(pycallback_object_count++)
69  {
70  d_callback = NULL;
71  setup_rpc();
72  }
73 
74  void add_rpc_variable(rpcbasic_sptr s)
75  {
76  d_rpc_vars.push_back(s);
77  }
78 
79  myType get() {
80  myType rVal = d_deflt;
81  if(d_callback == NULL) {
82  printf("WARNING: pycallback_object get() called without py callback set!\n");
83  return rVal;
84  }
85  else {
86  // obtain PyGIL
87  PyGILState_STATE state = PyGILState_Ensure();
88 
89  PyObject *func;
90  //PyObject *arglist;
91  PyObject *result;
92 
93  func = (PyObject *) d_callback; // Get Python function
94  //arglist = Py_BuildValue(""); // Build argument list
95  result = PyEval_CallObject(func,NULL); // Call Python
96  //result = PyEval_CallObject(func,arglist); // Call Python
97  //Py_DECREF(arglist); // Trash arglist
98  if(result) { // If no errors, return double
99  rVal = pyCast(result);
100  }
101  Py_XDECREF(result);
102 
103  // release PyGIL
104  PyGILState_Release(state);
105  return rVal;
106  }
107  }
108 
109  void set_callback(PyObject *cb)
110  {
111  d_callback = cb;
112  }
113 
114  void setup_rpc()
115  {
116 #ifdef GR_CTRLPORT
119  (boost::format("%s%d") % d_name % d_id).str() , d_functionbase.c_str(),
122  d_units.c_str(), d_desc.c_str(), RPC_PRIVLVL_MIN, d_dtype)));
123 #endif /* GR_CTRLPORT */
124  }
125 
126 private:
127  PyObject* d_callback;
128  std::string d_functionbase, d_units, d_desc;
129  myType d_min, d_max, d_deflt;
130  DisplayType d_dtype;
131 
132  /* This is a fall-through converter in case someone tries to call pyCast on an
133  * object type for which there isn't a template specialization (located below
134  * this class) function. This function should never get called, and it is
135  * unknown if changing the return type from myType to 'void' will break
136  * something. */
137  myType pyCast(PyObject* obj) {
138  printf("TYPE NOT IMPLEMENTED!\n");
139  assert(0);
140  // the following is to make compilers happy only.
141  myType dummy;
142  return(dummy);
143  };
144 
145  std::vector<boost::any> 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  return std::string(PyString_AsString(obj));
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++){ rval[i] = \
194  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:30
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:61
float min(float a, float b)
int pycallback_object_count
Definition: pycallback_object.h:33
void setup_rpc()
Definition: pycallback_object.h:114
static pmt::pmt_t make(myType _val)
Definition: pycallback_object.h:39
pyport_t
Definition: pycallback_object.h:28
Definition: rpccallbackregister_base.h:48
Definition: pycallback_object.h:58
Registers a 'get' function to get a parameter over ControlPort.
Definition: rpcregisterhelpers.h:987
std::complex< float > gr_complex
Definition: gr_complex.h:27
void set_callback(PyObject *cb)
Definition: pycallback_object.h:109
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:29
void add_rpc_variable(rpcbasic_sptr s)
Definition: pycallback_object.h:74
boost::intrusive_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:56
Definition: pycallback_object.h:36
static pmt_t mp(const std::string &s)
Make pmt symbol.
Definition: pmt_sugar.h:36
myType get()
Definition: pycallback_object.h:79
uint32_t DisplayType
Definition: rpccallbackregister_base.h:29