Loading...
Searching...
No Matches
pycallback_object.h
Go to the documentation of this file.
/* -*- c++ -*- */
/*
* Copyright 2012 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
#include <gnuradio/rpcregisterhelpers.h>
#include <pythread.h>
#include <iostream>
enum pyport_t { PYPORT_STRING, PYPORT_FLOAT };
int pycallback_object_count = 500;
// a simple to-PMT converter template class-function
template <class myType>
class pmt_assist
{
public:
static pmt::pmt_t make(myType _val) { return pmt::mp(_val); }
};
/* template specializations for vectors that can't use pmt::mp() */
template <>
pmt::pmt_t pmt_assist<std::vector<float>>::make(std::vector<float> _val)
{
return pmt::init_f32vector(_val.size(), _val);
}
template <>
pmt::pmt_t pmt_assist<std::vector<gr_complex>>::make(std::vector<gr_complex> _val)
{
return pmt::init_c32vector(_val.size(), _val);
}
template <class myType>
class pycallback_object
{
public:
pycallback_object(std::string name,
std::string functionbase,
std::string units,
std::string desc,
myType min,
myType max,
myType deflt,
DisplayType dtype)
: d_callback(NULL),
d_functionbase(functionbase),
d_units(units),
d_desc(desc),
d_min(min),
d_max(max),
d_deflt(deflt),
d_dtype(dtype),
d_name(name),
d_id(pycallback_object_count++)
{
d_callback = NULL;
setup_rpc();
}
void add_rpc_variable(rpcbasic_sptr s) { d_rpc_vars.push_back(s); }
myType get()
{
myType rVal = d_deflt;
if (d_callback == NULL) {
std::cerr
<< "WARNING: pycallback_object get() called without py callback set!"
<< std::endl;
return rVal;
} else {
// obtain PyGIL
PyGILState_STATE state = PyGILState_Ensure();
PyObject* func;
// PyObject *arglist;
PyObject* result;
func = (PyObject*)d_callback; // Get Python function
// arglist = Py_BuildValue(""); // Build argument list
result = PyEval_CallObject(func, NULL); // Call Python
// result = PyEval_CallObject(func,arglist); // Call Python
// Py_DECREF(arglist); // Trash arglist
if (result) { // If no errors, return double
rVal = pyCast(result);
}
Py_XDECREF(result);
// release PyGIL
PyGILState_Release(state);
return rVal;
}
}
void set_callback(PyObject* cb) { d_callback = cb; }
void setup_rpc()
{
#ifdef GR_CTRLPORT
add_rpc_variable(
rpcbasic_sptr(new rpcbasic_register_get<pycallback_object, myType>(
d_name + std::to_string(d_id),
d_functionbase.c_str(),
this,
&pycallback_object::get,
pmt_assist<myType>::make(d_min),
pmt_assist<myType>::make(d_max),
pmt_assist<myType>::make(d_deflt),
d_units.c_str(),
d_desc.c_str(),
RPC_PRIVLVL_MIN,
d_dtype)));
#endif /* GR_CTRLPORT */
}
private:
PyObject* d_callback;
std::string d_functionbase, d_units, d_desc;
myType d_min, d_max, d_deflt;
DisplayType d_dtype;
/* This is a fall-through converter in case someone tries to call pyCast on an
* object type for which there isn't a template specialization (located below
* this class) function. This function should never get called, and it is
* unknown if changing the return type from myType to 'void' will break
* something. */
myType pyCast(PyObject* obj)
{
std::cerr << "TYPE NOT IMPLEMENTED!" << std::endl;
assert(0);
// the following is to make compilers happy only.
myType dummy;
return (dummy);
};
std::vector<rpcbasic_sptr> d_rpc_vars; // container for all RPC variables
std::string d_name;
int d_id;
};
// template specialization conversion functions
// get data out of the PyObject and into the real world
template <>
std::string pycallback_object<std::string>::pyCast(PyObject* obj)
{
#if PY_MAJOR_VERSION >= 3
return std::string(PyUnicode_AsUTF8(obj));
#else
return std::string(PyString_AsString(obj));
#endif
}
template <>
double pycallback_object<double>::pyCast(PyObject* obj)
{
return PyFloat_AsDouble(obj);
}
template <>
float pycallback_object<float>::pyCast(PyObject* obj)
{
return (float)PyFloat_AsDouble(obj);
}
template <>
int pycallback_object<int>::pyCast(PyObject* obj)
{
return PyInt_AsLong(obj);
}
template <>
std::vector<float> pycallback_object<std::vector<float>>::pyCast(PyObject* obj)
{
int size = PyObject_Size(obj);
std::vector<float> rval(size);
for (int i = 0; i < size; i++) {
rval[i] = (float)PyFloat_AsDouble(PyList_GetItem(obj, i));
}
return rval;
}
template <>
std::vector<gr_complex> pycallback_object<std::vector<gr_complex>>::pyCast(PyObject* obj)
{
int size = PyObject_Size(obj);
std::vector<gr_complex> rval(size);
for (int i = 0; i < size; i++) {
rval[i] = gr_complex((float)PyComplex_RealAsDouble(PyList_GetItem(obj, i)),
(float)PyComplex_ImagAsDouble(PyList_GetItem(obj, i)));
}
return rval;
}
// TODO: add more template specializations as needed!
pmt_assist
Definition pycallback_object.h:23
pmt_assist::make
static pmt::pmt_t make(myType _val)
Definition pycallback_object.h:25
pycallback_object
Definition pycallback_object.h:43
pycallback_object::pycallback_object
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
pycallback_object::set_callback
void set_callback(PyObject *cb)
Definition pycallback_object.h:102
pycallback_object::add_rpc_variable
void add_rpc_variable(rpcbasic_sptr s)
Definition pycallback_object.h:68
pycallback_object::setup_rpc
void setup_rpc()
Definition pycallback_object.h:104
pycallback_object::get
myType get()
Definition pycallback_object.h:70
rpcbasic_register_get
Registers a 'get' function to get a parameter over ControlPort.
Definition rpcregisterhelpers.h:1107
gr_complex
std::complex< float > gr_complex
Definition gr_complex.h:15
pmt::init_f32vector
PMT_API pmt_t init_f32vector(size_t k, const float *data)
pmt::init_c32vector
PMT_API pmt_t init_c32vector(size_t k, const std::complex< float > *data)
pmt::mp
static pmt_t mp(const std::string &s)
Make pmt symbol.
Definition pmt_sugar.h:24
pmt::pmt_t
std::shared_ptr< pmt_base > pmt_t
typedef for shared pointer (transparent reference counting).
Definition pmt.h:83
pycallback_object_count
int pycallback_object_count
Definition pycallback_object.h:18
pyport_t
pyport_t
Definition pycallback_object.h:16
PYPORT_FLOAT
@ PYPORT_FLOAT
Definition pycallback_object.h:16
PYPORT_STRING
@ PYPORT_STRING
Definition pycallback_object.h:16
RPC_PRIVLVL_MIN
@ RPC_PRIVLVL_MIN
Definition rpccallbackregister_base.h:34
DisplayType
uint32_t DisplayType
Definition rpccallbackregister_base.h:17
rpcregisterhelpers.h