GNU Radio 3.7.1 C++ API
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>
27 #include <pythread.h>
28 #include <boost/format.hpp>
29 
30 enum pyport_t {
33 };
34 
35 class Instance
36 {
37 public:
39  {
41  }
42  static Ice::CommunicatorPtr get_swig_communicator()
43  {
44  return get_application()->communicator();
45  }
46 };
47 
49 
50 // a simple to-PMT converter template class-function
51 template <class myType> class pmt_assist
52 {
53 public:
54  static pmt::pmt_t make(myType _val)
55  {
56  return pmt::mp(_val);
57  }
58 };
59 
60 /* template specializations for vectors that cant use pmt::mp() */
61 template<>
62 pmt::pmt_t pmt_assist<std::vector<float> >::make(std::vector<float> _val)
63 {
64  return pmt::init_f32vector(_val.size(), &_val[0]);
65 }
66 
67 template<>
68 pmt::pmt_t pmt_assist<std::vector<gr_complex> >::make(std::vector<gr_complex> _val)
69 {
70  return pmt::init_c32vector(_val.size(), &_val[0]);
71 }
72 
73 template <class myType> class pycallback_object
74 {
75 public:
76  pycallback_object(std::string name, std::string functionbase,
77  std::string units, std::string desc,
78  myType min, myType max, myType deflt,
79  DisplayType dtype) :
80  d_callback(NULL),
81  d_functionbase(functionbase), d_units(units), d_desc(desc),
82  d_min(min), d_max(max), d_deflt(deflt), d_dtype(dtype),
83  d_name(name), d_id(pycallback_object_count++)
84  {
85  d_callback = NULL;
86  setup_rpc();
87  }
88 
90  {
91  d_rpc_vars.push_back(s);
92  }
93 
94  myType get() {
95  myType rVal;
96  if(d_callback == NULL) {
97  printf("WARNING: pycallback_object get() called without py callback set!\n");
98  return rVal;
99  }
100  else {
101  // obtain PyGIL
102  PyGILState_STATE state = PyGILState_Ensure();
103 
104  PyObject *func;
105  //PyObject *arglist;
106  PyObject *result;
107 
108  func = (PyObject *) d_callback; // Get Python function
109  //arglist = Py_BuildValue(""); // Build argument list
110  result = PyEval_CallObject(func,NULL); // Call Python
111  //result = PyEval_CallObject(func,arglist); // Call Python
112  //Py_DECREF(arglist); // Trash arglist
113  if(result) { // If no errors, return double
114  rVal = pyCast(result);
115  }
116  Py_XDECREF(result);
117 
118  // release PyGIL
119  PyGILState_Release(state);
120  return rVal;
121  }
122  }
123 
124  void set_callback(PyObject *cb)
125  {
126  d_callback = cb;
127  }
128 
129  void setup_rpc()
130  {
131 #ifdef GR_CTRLPORT
134  (boost::format("%s%d") % d_name % d_id).str() , d_functionbase.c_str(),
137  d_units.c_str(), d_desc.c_str(), RPC_PRIVLVL_MIN, d_dtype)));
138 #endif /* GR_CTRLPORT */
139  }
140 
141 private:
142  PyObject* d_callback;
143  std::string d_functionbase, d_units, d_desc;
144  myType d_min, d_max, d_deflt;
145  DisplayType d_dtype;
146 
147  myType pyCast(PyObject* obj) {
148  printf("TYPE NOT IMPLEMENTED!\n");
149  assert(0);
150  };
151  std::vector<boost::any> d_rpc_vars; // container for all RPC variables
152  std::string d_name;
153  int d_id;
154 
155 };
156 
157 
158 // template specialization conversion functions
159 // get data out of the PyObject and into the real world
160 template<>
161 std::string pycallback_object<std::string>::pyCast(PyObject* obj)
162 {
163  return std::string(PyString_AsString(obj));
164 }
165 
166 template<>
167 double pycallback_object<double>::pyCast(PyObject* obj)
168 {
169  return PyFloat_AsDouble(obj);
170 }
171 
172 template<>
173 float pycallback_object<float>::pyCast(PyObject* obj)
174 {
175  return (float)PyFloat_AsDouble(obj);
176 }
177 
178 template<>
179 int pycallback_object<int>::pyCast(PyObject* obj)
180 {
181  return PyInt_AsLong(obj);
182 }
183 
184 template<>
185 std::vector<float> pycallback_object<std::vector<float> >::pyCast(PyObject* obj)
186 {
187  int size = PyObject_Size(obj);
188  std::vector<float> rval(size);
189  for(int i=0; i<size; i++) {
190  rval[i] = (float)PyFloat_AsDouble(PyList_GetItem(obj, i));
191  }
192  return rval;
193 }
194 
195 template<>
196 std::vector<gr_complex> pycallback_object<std::vector<gr_complex> >::pyCast(PyObject* obj)
197 {
198  int size = PyObject_Size(obj);
199  std::vector<gr_complex> rval(size);
200  for(int i=0; i<size; i++){ rval[i] = \
201  gr_complex((float)PyComplex_RealAsDouble(PyList_GetItem(obj, i)),
202  (float)PyComplex_ImagAsDouble(PyList_GetItem(obj, i)));
203  }
204  return rval;
205 }
206 // TODO: add more template specializations as needed!