GNU Radio 3.7.1 C++ API
|
00001 /* -*- c++ -*- */ 00002 /* 00003 * Copyright 2012 Free Software Foundation, Inc. 00004 * 00005 * This file is part of GNU Radio 00006 * 00007 * GNU Radio is free software; you can redistribute it and/or modify 00008 * it under the terms of the GNU General Public License as published by 00009 * the Free Software Foundation; either version 3, or (at your option) 00010 * any later version. 00011 * 00012 * GNU Radio is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 * GNU General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU General Public License 00018 * along with GNU Radio; see the file COPYING. If not, write to 00019 * the Free Software Foundation, Inc., 51 Franklin Street, 00020 * Boston, MA 02110-1301, USA. 00021 */ 00022 00023 #include <iostream> 00024 #include <gnuradio/rpcregisterhelpers.h> 00025 #include <gnuradio/ice_application_base.h> 00026 #include <gnuradio/IcePy_Communicator.h> 00027 #include <pythread.h> 00028 #include <boost/format.hpp> 00029 00030 enum pyport_t { 00031 PYPORT_STRING, 00032 PYPORT_FLOAT 00033 }; 00034 00035 class Instance 00036 { 00037 public: 00038 static boost::shared_ptr<ice_application_common> get_application() 00039 { 00040 return ice_application_common::Instance(); 00041 } 00042 static Ice::CommunicatorPtr get_swig_communicator() 00043 { 00044 return get_application()->communicator(); 00045 } 00046 }; 00047 00048 int pycallback_object_count = 500; 00049 00050 // a simple to-PMT converter template class-function 00051 template <class myType> class pmt_assist 00052 { 00053 public: 00054 static pmt::pmt_t make(myType _val) 00055 { 00056 return pmt::mp(_val); 00057 } 00058 }; 00059 00060 /* template specializations for vectors that cant use pmt::mp() */ 00061 template<> 00062 pmt::pmt_t pmt_assist<std::vector<float> >::make(std::vector<float> _val) 00063 { 00064 return pmt::init_f32vector(_val.size(), &_val[0]); 00065 } 00066 00067 template<> 00068 pmt::pmt_t pmt_assist<std::vector<gr_complex> >::make(std::vector<gr_complex> _val) 00069 { 00070 return pmt::init_c32vector(_val.size(), &_val[0]); 00071 } 00072 00073 template <class myType> class pycallback_object 00074 { 00075 public: 00076 pycallback_object(std::string name, std::string functionbase, 00077 std::string units, std::string desc, 00078 myType min, myType max, myType deflt, 00079 DisplayType dtype) : 00080 d_callback(NULL), 00081 d_functionbase(functionbase), d_units(units), d_desc(desc), 00082 d_min(min), d_max(max), d_deflt(deflt), d_dtype(dtype), 00083 d_name(name), d_id(pycallback_object_count++) 00084 { 00085 d_callback = NULL; 00086 setup_rpc(); 00087 } 00088 00089 void add_rpc_variable(rpcbasic_sptr s) 00090 { 00091 d_rpc_vars.push_back(s); 00092 } 00093 00094 myType get() { 00095 myType rVal; 00096 if(d_callback == NULL) { 00097 printf("WARNING: pycallback_object get() called without py callback set!\n"); 00098 return rVal; 00099 } 00100 else { 00101 // obtain PyGIL 00102 PyGILState_STATE state = PyGILState_Ensure(); 00103 00104 PyObject *func; 00105 //PyObject *arglist; 00106 PyObject *result; 00107 00108 func = (PyObject *) d_callback; // Get Python function 00109 //arglist = Py_BuildValue(""); // Build argument list 00110 result = PyEval_CallObject(func,NULL); // Call Python 00111 //result = PyEval_CallObject(func,arglist); // Call Python 00112 //Py_DECREF(arglist); // Trash arglist 00113 if(result) { // If no errors, return double 00114 rVal = pyCast(result); 00115 } 00116 Py_XDECREF(result); 00117 00118 // release PyGIL 00119 PyGILState_Release(state); 00120 return rVal; 00121 } 00122 } 00123 00124 void set_callback(PyObject *cb) 00125 { 00126 d_callback = cb; 00127 } 00128 00129 void setup_rpc() 00130 { 00131 #ifdef GR_CTRLPORT 00132 add_rpc_variable( 00133 rpcbasic_sptr(new rpcbasic_register_get<pycallback_object, myType>( 00134 (boost::format("%s%d") % d_name % d_id).str() , d_functionbase.c_str(), 00135 this, &pycallback_object::get, pmt_assist<myType>::make(d_min), 00136 pmt_assist<myType>::make(d_max), pmt_assist<myType>::make(d_deflt), 00137 d_units.c_str(), d_desc.c_str(), RPC_PRIVLVL_MIN, d_dtype))); 00138 #endif /* GR_CTRLPORT */ 00139 } 00140 00141 private: 00142 PyObject* d_callback; 00143 std::string d_functionbase, d_units, d_desc; 00144 myType d_min, d_max, d_deflt; 00145 DisplayType d_dtype; 00146 00147 myType pyCast(PyObject* obj) { 00148 printf("TYPE NOT IMPLEMENTED!\n"); 00149 assert(0); 00150 }; 00151 std::vector<boost::any> d_rpc_vars; // container for all RPC variables 00152 std::string d_name; 00153 int d_id; 00154 00155 }; 00156 00157 00158 // template specialization conversion functions 00159 // get data out of the PyObject and into the real world 00160 template<> 00161 std::string pycallback_object<std::string>::pyCast(PyObject* obj) 00162 { 00163 return std::string(PyString_AsString(obj)); 00164 } 00165 00166 template<> 00167 double pycallback_object<double>::pyCast(PyObject* obj) 00168 { 00169 return PyFloat_AsDouble(obj); 00170 } 00171 00172 template<> 00173 float pycallback_object<float>::pyCast(PyObject* obj) 00174 { 00175 return (float)PyFloat_AsDouble(obj); 00176 } 00177 00178 template<> 00179 int pycallback_object<int>::pyCast(PyObject* obj) 00180 { 00181 return PyInt_AsLong(obj); 00182 } 00183 00184 template<> 00185 std::vector<float> pycallback_object<std::vector<float> >::pyCast(PyObject* obj) 00186 { 00187 int size = PyObject_Size(obj); 00188 std::vector<float> rval(size); 00189 for(int i=0; i<size; i++) { 00190 rval[i] = (float)PyFloat_AsDouble(PyList_GetItem(obj, i)); 00191 } 00192 return rval; 00193 } 00194 00195 template<> 00196 std::vector<gr_complex> pycallback_object<std::vector<gr_complex> >::pyCast(PyObject* obj) 00197 { 00198 int size = PyObject_Size(obj); 00199 std::vector<gr_complex> rval(size); 00200 for(int i=0; i<size; i++){ rval[i] = \ 00201 gr_complex((float)PyComplex_RealAsDouble(PyList_GetItem(obj, i)), 00202 (float)PyComplex_ImagAsDouble(PyList_GetItem(obj, i))); 00203 } 00204 return rval; 00205 } 00206 // TODO: add more template specializations as needed!