summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosh Morman <mormjb@gmail.com>2020-04-23 09:58:59 -0400
committerJosh Morman <mormjb@gmail.com>2020-06-04 10:05:47 -0400
commit0249f7ce0cf5173b946b936c5cd66380afc8bf92 (patch)
tree587f3da2a664c9589fdc7a1d0533a8b76af0c3ec
parent5322a1ff0066bee025b2ea9af550aad4b461d5e0 (diff)
runtime: replace py gateway with pybind11 support, remove feval
-rw-r--r--gnuradio-runtime/include/gnuradio/CMakeLists.txt2
-rw-r--r--gnuradio-runtime/include/gnuradio/block_gateway.h282
-rw-r--r--gnuradio-runtime/include/gnuradio/feval.h175
-rw-r--r--gnuradio-runtime/include/gnuradio/py_feval.h86
-rw-r--r--gnuradio-runtime/lib/CMakeLists.txt5
-rw-r--r--gnuradio-runtime/lib/block_gateway_impl.cc137
-rw-r--r--gnuradio-runtime/lib/block_gateway_impl.h56
-rw-r--r--gnuradio-runtime/lib/feval.cc74
-rw-r--r--gnuradio-runtime/python/gnuradio/gr/qa_feval.py99
9 files changed, 99 insertions, 817 deletions
diff --git a/gnuradio-runtime/include/gnuradio/CMakeLists.txt b/gnuradio-runtime/include/gnuradio/CMakeLists.txt
index 056af5d6f4..d8e9c193ee 100644
--- a/gnuradio-runtime/include/gnuradio/CMakeLists.txt
+++ b/gnuradio-runtime/include/gnuradio/CMakeLists.txt
@@ -23,7 +23,6 @@ install(FILES
constants.h
endianness.h
expj.h
- feval.h
flowgraph.h
fxpt.h
fxpt_nco.h
@@ -42,7 +41,6 @@ install(FILES
msg_queue.h
nco.h
prefs.h
- py_feval.h
pycallback_object.h
random.h
realtime.h
diff --git a/gnuradio-runtime/include/gnuradio/block_gateway.h b/gnuradio-runtime/include/gnuradio/block_gateway.h
index bcf3a7b27d..e8e1df87e3 100644
--- a/gnuradio-runtime/include/gnuradio/block_gateway.h
+++ b/gnuradio-runtime/include/gnuradio/block_gateway.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2011-2013,2017 Free Software Foundation, Inc.
+ * Copyright 2011-2013,2017,2020 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -13,219 +13,55 @@
#include <gnuradio/api.h>
#include <gnuradio/block.h>
-#include <gnuradio/feval.h>
+#include <string>
-namespace gr {
-
-/*!
- * The work type enum tells the gateway what kind of block to
- * implement. The choices are familiar gnuradio block overloads
- * (sync, decim, interp).
- */
-enum block_gw_work_type {
- GR_BLOCK_GW_WORK_GENERAL,
- GR_BLOCK_GW_WORK_SYNC,
- GR_BLOCK_GW_WORK_DECIM,
- GR_BLOCK_GW_WORK_INTERP,
-};
-
-//! Magic return values from general_work, \ref gr::block::WORK_CALLED_PRODUCE
-enum block_gw_work_return_type { WORK_CALLED_PRODUCE = -2, WORK_DONE = -1 };
-enum tag_propagation_policy_t {
- TPP_DONT = 0,
- TPP_ALL_TO_ALL = 1,
- TPP_ONE_TO_ONE = 2,
- TPP_CUSTOM = 3
-};
-
-/*!
- * Shared message structure between python and gateway.
- * Each action type represents a scheduler-called function.
- */
-struct block_gw_message_type {
- enum action_type {
- ACTION_GENERAL_WORK, // dispatch work
- ACTION_WORK, // dispatch work
- ACTION_FORECAST, // dispatch forecast
- ACTION_START, // dispatch start
- ACTION_STOP, // dispatch stop
- };
-
- action_type action;
-
- int general_work_args_noutput_items;
- std::vector<int> general_work_args_ninput_items;
- std::vector<void*> general_work_args_input_items; // TODO this should be const void*,
- // but swig can't int cast it right
- std::vector<void*> general_work_args_output_items;
- int general_work_args_return_value;
-
- int work_args_ninput_items;
- int work_args_noutput_items;
- std::vector<void*> work_args_input_items; // TODO this should be const void*, but swig
- // can't int cast it right
- std::vector<void*> work_args_output_items;
- int work_args_return_value;
-
- int forecast_args_noutput_items;
- std::vector<int> forecast_args_ninput_items_required;
+#include <pybind11/pybind11.h> // must be first
+#include <pybind11/stl.h>
+namespace py = pybind11;
- bool start_args_return_value;
-
- bool stop_args_return_value;
-};
+namespace gr {
/*!
* The gateway block which performs all the magic.
*
* The gateway provides access to all the gr::block routines.
- * The methods prefixed with gr::block__ are renamed
- * to class methods without the prefix in python.
*/
+typedef enum {
+ GW_BLOCK_GENERAL = 0,
+ GW_BLOCK_SYNC,
+ GW_BLOCK_DECIM,
+ GW_BLOCK_INTERP
+} gw_block_t;
+
class GR_RUNTIME_API block_gateway : virtual public gr::block
{
+private:
+ py::handle d_py_handle;
public:
// gr::block_gateway::sptr
typedef std::shared_ptr<block_gateway> sptr;
/*!
* Make a new gateway block.
- * \param handler the swig director object with callback
+ * \param py_object the pybind11 object with callback
* \param name the name of the block (Ex: "Shirley")
* \param in_sig the input signature for this block
* \param out_sig the output signature for this block
- * \param work_type the type of block overload to implement
- * \param factor the decimation or interpolation factor
* \return a new gateway block
*/
- static sptr make(gr::feval_ll* handler,
+ static sptr make(const py::object& py_handle,
const std::string& name,
gr::io_signature::sptr in_sig,
- gr::io_signature::sptr out_sig,
- const block_gw_work_type work_type,
- const unsigned factor);
-
- //! Provide access to the shared message object
- virtual block_gw_message_type& block_message(void) = 0;
-
- long block__unique_id(void) const { return gr::block::unique_id(); }
-
- std::string block__name(void) const { return gr::block::name(); }
-
- unsigned block__history(void) const { return gr::block::history(); }
-
- void block__set_history(unsigned history) { return gr::block::set_history(history); }
-
- void block__set_block_alias(std::string alias)
- {
- return gr::block::set_block_alias(alias);
- }
-
- std::string block__alias(void) const { return gr::block::alias(); }
-
- void block__set_processor_affinity(std::vector<int> mask)
- {
- return gr::block::set_processor_affinity(mask);
- }
-
- void block__set_fixed_rate(bool fixed_rate)
- {
- return gr::block::set_fixed_rate(fixed_rate);
- }
-
- bool block__fixed_rate(void) const { return gr::block::fixed_rate(); }
-
- void block__set_output_multiple(int multiple)
- {
- return gr::block::set_output_multiple(multiple);
- }
-
- void block__set_min_output_buffer(int port, long size)
- {
- return gr::block::set_min_output_buffer(port, size);
- }
-
- void block__set_min_output_buffer(long size)
- {
- return gr::block::set_min_output_buffer(size);
- }
-
- long block__max_output_buffer(size_t i) { return gr::block::max_output_buffer(i); }
-
- void block__set_max_output_buffer(long max_output_buffer)
- {
- gr::block::set_max_output_buffer(max_output_buffer);
- }
-
- void block__set_max_output_buffer(int port, long max_output_buffer)
- {
- gr::block::set_max_output_buffer(port, max_output_buffer);
- }
-
- int block__output_multiple(void) const { return gr::block::output_multiple(); }
+ gr::io_signature::sptr out_sig);
- void block__consume(int which_input, int how_many_items)
- {
- return gr::block::consume(which_input, how_many_items);
- }
-
- void block__consume_each(int how_many_items)
- {
- return gr::block::consume_each(how_many_items);
- }
- void block__produce(int which_output, int how_many_items)
- {
- return gr::block::produce(which_output, how_many_items);
- }
-
- void block__set_relative_rate(double relative_rate)
- {
- return gr::block::set_relative_rate(relative_rate);
- }
-
- void block__set_inverse_relative_rate(double inverse_relative_rate)
- {
- return gr::block::set_inverse_relative_rate(inverse_relative_rate);
- }
-
- void block__set_relative_rate(uint64_t interpolation, uint64_t decimation)
- {
- return gr::block::set_relative_rate(interpolation, decimation);
- }
-
- double block__relative_rate(void) const { return gr::block::relative_rate(); }
-
- uint64_t block__relative_rate_i(void) const { return gr::block::relative_rate_i(); }
-
- uint64_t block__relative_rate_d(void) const { return gr::block::relative_rate_d(); }
-
- uint64_t block__nitems_read(unsigned int which_input)
- {
- return gr::block::nitems_read(which_input);
- }
-
- uint64_t block__nitems_written(unsigned int which_output)
- {
- return gr::block::nitems_written(which_output);
- }
-
- block::tag_propagation_policy_t block__tag_propagation_policy(void)
- {
- return gr::block::tag_propagation_policy();
- }
-
- void block__set_tag_propagation_policy(block::tag_propagation_policy_t p)
- {
- return gr::block::set_tag_propagation_policy(p);
- }
-
- void block__add_item_tag(unsigned int which_output, const tag_t& tag)
+ // Protected members of gr::block trampolined here for python blocks to use
+ void _add_item_tag(unsigned int which_output, const tag_t& tag)
{
return gr::block::add_item_tag(which_output, tag);
}
- void block__add_item_tag(unsigned int which_output,
+ void _add_item_tag(unsigned int which_output,
uint64_t abs_offset,
const pmt::pmt_t& key,
const pmt::pmt_t& value,
@@ -234,7 +70,8 @@ public:
return gr::block::add_item_tag(which_output, abs_offset, key, value, srcid);
}
- std::vector<tag_t> block__get_tags_in_range(unsigned int which_input,
+
+ std::vector<tag_t> _get_tags_in_range(unsigned int which_input,
uint64_t abs_start,
uint64_t abs_end)
{
@@ -243,7 +80,7 @@ public:
return tags;
}
- std::vector<tag_t> block__get_tags_in_range(unsigned int which_input,
+ std::vector<tag_t> _get_tags_in_range(unsigned int which_input,
uint64_t abs_start,
uint64_t abs_end,
const pmt::pmt_t& key)
@@ -253,7 +90,7 @@ public:
return tags;
}
- std::vector<tag_t> block__get_tags_in_window(unsigned int which_input,
+ std::vector<tag_t> _get_tags_in_window(unsigned int which_input,
uint64_t rel_start,
uint64_t rel_end)
{
@@ -262,7 +99,7 @@ public:
return tags;
}
- std::vector<tag_t> block__get_tags_in_window(unsigned int which_input,
+ std::vector<tag_t> _get_tags_in_window(unsigned int which_input,
uint64_t rel_start,
uint64_t rel_end,
const pmt::pmt_t& key)
@@ -272,73 +109,12 @@ public:
return tags;
}
- /* Message passing interface */
- void block__message_port_register_in(pmt::pmt_t port_id)
- {
- gr::basic_block::message_port_register_in(port_id);
- }
-
- void block__message_port_register_out(pmt::pmt_t port_id)
- {
- gr::basic_block::message_port_register_out(port_id);
- }
-
- void block__message_port_pub(pmt::pmt_t port_id, pmt::pmt_t msg)
- {
- gr::basic_block::message_port_pub(port_id, msg);
- }
-
- void block__message_port_sub(pmt::pmt_t port_id, pmt::pmt_t target)
- {
- gr::basic_block::message_port_sub(port_id, target);
- }
-
- void block__message_port_unsub(pmt::pmt_t port_id, pmt::pmt_t target)
- {
- gr::basic_block::message_port_unsub(port_id, target);
- }
-
- pmt::pmt_t block__message_subscribers(pmt::pmt_t which_port)
- {
- return gr::basic_block::message_subscribers(which_port);
- }
-
- pmt::pmt_t block__message_ports_in() { return gr::basic_block::message_ports_in(); }
-
- pmt::pmt_t block__message_ports_out() { return gr::basic_block::message_ports_out(); }
-
- void set_msg_handler_feval(pmt::pmt_t which_port, gr::feval_p* msg_handler)
- {
- if (msg_queue.find(which_port) == msg_queue.end()) {
- throw std::runtime_error(
- "attempt to set_msg_handler_feval() on bad input message port!");
- }
- d_msg_handlers_feval[which_port] = msg_handler;
- }
+ virtual void set_msg_handler_pybind(pmt::pmt_t which_port, std::string& handler_name) = 0;
protected:
- typedef std::map<pmt::pmt_t, feval_p*, pmt::comparator> msg_handlers_feval_t;
- msg_handlers_feval_t d_msg_handlers_feval;
-
- bool has_msg_handler(pmt::pmt_t which_port)
- {
- if (d_msg_handlers_feval.find(which_port) != d_msg_handlers_feval.end()) {
- return true;
- } else {
- return gr::basic_block::has_msg_handler(which_port);
- }
- }
+ virtual bool has_msg_handler(pmt::pmt_t which_port) = 0;
+ virtual void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg) = 0;
- void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg)
- {
- // Is there a handler?
- if (d_msg_handlers_feval.find(which_port) != d_msg_handlers_feval.end()) {
- d_msg_handlers_feval[which_port]->calleval(msg); // Yes, invoke it.
- } else {
- // Pass to generic dispatcher if not found
- gr::basic_block::dispatch_msg(which_port, msg);
- }
- }
};
} /* namespace gr */
diff --git a/gnuradio-runtime/include/gnuradio/feval.h b/gnuradio-runtime/include/gnuradio/feval.h
deleted file mode 100644
index 0148aea89c..0000000000
--- a/gnuradio-runtime/include/gnuradio/feval.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006,2013 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * SPDX-License-Identifier: GPL-3.0-or-later
- *
- */
-
-#ifndef INCLUDED_GR_FEVAL_H
-#define INCLUDED_GR_FEVAL_H
-
-#include <gnuradio/api.h>
-#include <gnuradio/gr_complex.h>
-#include <pmt/pmt.h>
-
-namespace gr {
-
-/*!
- * \brief base class for evaluating a function: double -> double
- * \ingroup misc
- *
- * This class is designed to be subclassed in Python or C++ and is
- * callable from both places. It uses SWIG's "director" feature to
- * implement the magic.
- *
- * It's slow. Don't use it in a performance critical path.
- *
- * Override eval to define the behavior.
- * Use calleval to invoke eval (this kludge is required to allow a
- * python specific "shim" to be inserted.
- */
-class GR_RUNTIME_API feval_dd
-{
-protected:
- /*!
- * \brief override this to define the function
- */
- virtual double eval(double x);
-
-public:
- feval_dd() {}
- virtual ~feval_dd();
-
- virtual double calleval(double x); // invoke "eval"
-};
-
-/*!
- * \brief base class for evaluating a function: complex -> complex
- * \ingroup misc
- *
- * This class is designed to be subclassed in Python or C++ and is
- * callable from both places. It uses SWIG's "director" feature to
- * implement the magic.
- *
- * It's slow. Don't use it in a performance critical path.
- *
- * Override eval to define the behavior.
- * Use calleval to invoke eval (this kludge is required to allow a
- * python specific "shim" to be inserted.
- */
-class GR_RUNTIME_API feval_cc
-{
-protected:
- /*!
- * \brief override this to define the function
- */
- virtual gr_complex eval(gr_complex x);
-
-public:
- feval_cc() {}
- virtual ~feval_cc();
-
- virtual gr_complex calleval(gr_complex x); // invoke "eval"
-};
-
-/*!
- * \brief base class for evaluating a function: long -> long
- * \ingroup misc
- *
- * This class is designed to be subclassed in Python or C++ and is
- * callable from both places. It uses SWIG's "director" feature to
- * implement the magic.
- *
- * It's slow. Don't use it in a performance critical path.
- *
- * Override eval to define the behavior.
- * Use calleval to invoke eval (this kludge is required to allow a
- * python specific "shim" to be inserted.
- */
-class GR_RUNTIME_API feval_ll
-{
-protected:
- /*!
- * \brief override this to define the function
- */
- virtual long eval(long x);
-
-public:
- feval_ll() {}
- virtual ~feval_ll();
-
- virtual long calleval(long x); // invoke "eval"
-};
-
-/*!
- * \brief base class for evaluating a function: void -> void
- * \ingroup misc
- *
- * This class is designed to be subclassed in Python or C++ and is
- * callable from both places. It uses SWIG's "director" feature to
- * implement the magic.
- *
- * It's slow. Don't use it in a performance critical path.
- *
- * Override eval to define the behavior.
- * Use calleval to invoke eval (this kludge is required to allow a
- * python specific "shim" to be inserted.
- */
-class GR_RUNTIME_API feval
-{
-protected:
- /*!
- * \brief override this to define the function
- */
- virtual void eval();
-
-public:
- feval() {}
- virtual ~feval();
-
- virtual void calleval(); // invoke "eval"
-};
-
-/*!
- * \brief base class for evaluating a function: pmt -> void
- * \ingroup misc
- *
- * This class is designed to be subclassed in Python or C++ and is
- * callable from both places. It uses SWIG's "director" feature to
- * implement the magic.
- *
- * It's slow. Don't use it in a performance critical path.
- *
- * Override eval to define the behavior.
- * Use calleval to invoke eval (this kludge is required to allow a
- * python specific "shim" to be inserted.
- */
-class GR_RUNTIME_API feval_p
-{
-protected:
- /*!
- * \brief override this to define the function
- */
- virtual void eval(pmt::pmt_t x);
-
-public:
- feval_p() {}
- virtual ~feval_p();
-
- virtual void calleval(pmt::pmt_t x); // invoke "eval"
-};
-
-/*!
- * \brief trivial examples / test cases showing C++ calling Python code
- */
-GR_RUNTIME_API double feval_dd_example(feval_dd* f, double x);
-GR_RUNTIME_API gr_complex feval_cc_example(feval_cc* f, gr_complex x);
-GR_RUNTIME_API long feval_ll_example(feval_ll* f, long x);
-GR_RUNTIME_API void feval_example(feval* f);
-
-} /* namespace gr */
-
-#endif /* INCLUDED_GR_FEVAL_H */
diff --git a/gnuradio-runtime/include/gnuradio/py_feval.h b/gnuradio-runtime/include/gnuradio/py_feval.h
deleted file mode 100644
index 50af37ec03..0000000000
--- a/gnuradio-runtime/include/gnuradio/py_feval.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006,2013 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * SPDX-License-Identifier: GPL-3.0-or-later
- *
- */
-
-#ifndef INCLUDED_GR_PY_FEVAL_H
-#define INCLUDED_GR_PY_FEVAL_H
-
-#include <gnuradio/feval.h>
-#include <Python.h>
-#include <pmt/pmt.h>
-
-class ensure_py_gil_state
-{
- PyGILState_STATE d_gstate;
-
-public:
- ensure_py_gil_state() { d_gstate = PyGILState_Ensure(); }
- ~ensure_py_gil_state() { PyGILState_Release(d_gstate); }
-};
-
-namespace gr {
-
-class GR_RUNTIME_API py_feval_dd : public feval_dd
-{
-public:
- double calleval(double x)
- {
- ensure_py_gil_state _lock;
- return eval(x);
- }
- virtual ~py_feval_dd(){};
-};
-
-class GR_RUNTIME_API py_feval_cc : public feval_cc
-{
-public:
- gr_complex calleval(gr_complex x)
- {
- ensure_py_gil_state _lock;
- return eval(x);
- }
- virtual ~py_feval_cc(){};
-};
-
-class GR_RUNTIME_API py_feval_ll : public feval_ll
-{
-public:
- long calleval(long x)
- {
- ensure_py_gil_state _lock;
- return eval(x);
- }
- virtual ~py_feval_ll(){};
-};
-
-class GR_RUNTIME_API py_feval : public feval
-{
-public:
- void calleval()
- {
- ensure_py_gil_state _lock;
- eval();
- }
- virtual ~py_feval(){};
-};
-
-class GR_RUNTIME_API py_feval_p : public feval_p
-{
-public:
- void calleval(pmt::pmt_t x)
- {
- ensure_py_gil_state _lock;
- eval(x);
- }
- virtual ~py_feval_p(){};
-};
-
-} /* namespace gr */
-
-#endif /* INCLUDED_GR_PY_FEVAL_H */
diff --git a/gnuradio-runtime/lib/CMakeLists.txt b/gnuradio-runtime/lib/CMakeLists.txt
index ee89f363ce..65673ad699 100644
--- a/gnuradio-runtime/lib/CMakeLists.txt
+++ b/gnuradio-runtime/lib/CMakeLists.txt
@@ -47,7 +47,6 @@ add_library(gnuradio-runtime
block_gateway_impl.cc
block_registry.cc
buffer.cc
- feval.cc
flat_flowgraph.cc
flowgraph.cc
hier_block2.cc
@@ -196,10 +195,14 @@ target_link_libraries(gnuradio-runtime PUBLIC
Boost::thread
Log4Cpp::log4cpp
MPLib::mplib
+ ${PYTHON_LIBRARIES}
)
target_include_directories(gnuradio-runtime
PUBLIC
+ ${PYTHON_INCLUDE_DIR}
+ ${PYTHON_NUMPY_INCLUDE_DIR}
+ ${pybind11_INCLUDE_DIR}
$<INSTALL_INTERFACE:${CMAKE_INSTALL_PREFIX}/include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../include>
diff --git a/gnuradio-runtime/lib/block_gateway_impl.cc b/gnuradio-runtime/lib/block_gateway_impl.cc
index 4acb464511..ced8edd1f5 100644
--- a/gnuradio-runtime/lib/block_gateway_impl.cc
+++ b/gnuradio-runtime/lib/block_gateway_impl.cc
@@ -1,93 +1,45 @@
+/* -*- c++ -*- */
/*
- * Copyright 2011-2013 Free Software Foundation, Inc.
+ * Copyright 2013,2020 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
* SPDX-License-Identifier: GPL-3.0-or-later
*
*/
-
#include "block_gateway_impl.h"
+#include <pybind11/embed.h>
+
#include <gnuradio/io_signature.h>
-#include <boost/bind.hpp>
#include <iostream>
namespace gr {
-/***********************************************************************
- * Helper routines
- **********************************************************************/
-template <typename OutType, typename InType>
-void copy_pointers(OutType& out, const InType& in)
-{
- out.resize(in.size());
- for (size_t i = 0; i < in.size(); i++) {
- out[i] = (void*)(in[i]);
- }
-}
-
-
-block_gateway::sptr block_gateway::make(feval_ll* handler,
+block_gateway::sptr block_gateway::make(const py::object& p,
const std::string& name,
gr::io_signature::sptr in_sig,
- gr::io_signature::sptr out_sig,
- const block_gw_work_type work_type,
- const unsigned factor)
+ gr::io_signature::sptr out_sig)
{
return block_gateway::sptr(
- new block_gateway_impl(handler, name, in_sig, out_sig, work_type, factor));
+ new block_gateway_impl(p, name, in_sig, out_sig));
}
-block_gateway_impl::block_gateway_impl(feval_ll* handler,
+block_gateway_impl::block_gateway_impl(const py::handle& p,
const std::string& name,
gr::io_signature::sptr in_sig,
- gr::io_signature::sptr out_sig,
- const block_gw_work_type work_type,
- const unsigned factor)
- : block(name, in_sig, out_sig), _handler(handler), _work_type(work_type)
+ gr::io_signature::sptr out_sig)
+ : block(name, in_sig, out_sig)
{
- switch (_work_type) {
- case GR_BLOCK_GW_WORK_GENERAL:
- _decim = 1; // not relevant, but set anyway
- _interp = 1; // not relevant, but set anyway
- break;
-
- case GR_BLOCK_GW_WORK_SYNC:
- _decim = 1;
- _interp = 1;
- this->set_fixed_rate(true);
- break;
-
- case GR_BLOCK_GW_WORK_DECIM:
- _decim = factor;
- _interp = 1;
- break;
-
- case GR_BLOCK_GW_WORK_INTERP:
- _decim = 1;
- _interp = factor;
- this->set_output_multiple(_interp);
- break;
- }
+ _py_handle = p;
}
void block_gateway_impl::forecast(int noutput_items, gr_vector_int& ninput_items_required)
{
- switch (_work_type) {
- case GR_BLOCK_GW_WORK_GENERAL:
- _message.action = block_gw_message_type::ACTION_FORECAST;
- _message.forecast_args_noutput_items = noutput_items;
- _message.forecast_args_ninput_items_required = ninput_items_required;
- _handler->calleval(0);
- ninput_items_required = _message.forecast_args_ninput_items_required;
- return;
+ py::gil_scoped_acquire acquire;
+
+ py::object ret_ninput_items_required = _py_handle.attr("handle_forecast")(noutput_items, ninput_items_required.size());
+ ninput_items_required = ret_ninput_items_required.cast<std::vector<int>>();
- default:
- unsigned ninputs = ninput_items_required.size();
- for (unsigned i = 0; i < ninputs; i++)
- ninput_items_required[i] = fixed_rate_noutput_to_ninput(noutput_items);
- return;
- }
}
int block_gateway_impl::general_work(int noutput_items,
@@ -95,63 +47,28 @@ int block_gateway_impl::general_work(int noutput_items,
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items)
{
- switch (_work_type) {
- case GR_BLOCK_GW_WORK_GENERAL:
- _message.action = block_gw_message_type::ACTION_GENERAL_WORK;
- _message.general_work_args_noutput_items = noutput_items;
- _message.general_work_args_ninput_items = ninput_items;
- copy_pointers(_message.general_work_args_input_items, input_items);
- _message.general_work_args_output_items = output_items;
- _handler->calleval(0);
- return _message.general_work_args_return_value;
+ py::gil_scoped_acquire acquire;
- default:
- int r = work(noutput_items, input_items, output_items);
- if (r > 0)
- consume_each(r * _decim / _interp);
- return r;
- }
+ py::object ret = _py_handle.attr("handle_general_work")(noutput_items, ninput_items, input_items, output_items);
+
+ return ret.cast<int>();;
}
-int block_gateway_impl::work(int noutput_items,
- gr_vector_const_void_star& input_items,
- gr_vector_void_star& output_items)
+bool block_gateway_impl::start(void)
{
- _message.action = block_gw_message_type::ACTION_WORK;
- _message.work_args_ninput_items = fixed_rate_noutput_to_ninput(noutput_items);
- if (_message.work_args_ninput_items == 0)
- return -1;
- _message.work_args_noutput_items = noutput_items;
- copy_pointers(_message.work_args_input_items, input_items);
- _message.work_args_output_items = output_items;
- _handler->calleval(0);
- return _message.work_args_return_value;
-}
+ py::gil_scoped_acquire acquire;
-int block_gateway_impl::fixed_rate_noutput_to_ninput(int noutput_items)
-{
- return (noutput_items * _decim / _interp) + history() - 1;
+ py::object ret = _py_handle.attr("start")();
+ return ret.cast<bool>();
}
-int block_gateway_impl::fixed_rate_ninput_to_noutput(int ninput_items)
+bool block_gateway_impl::stop(void)
{
- return std::max(0, ninput_items - (int)history() + 1) * _interp / _decim;
-}
+ py::gil_scoped_acquire acquire;
-bool block_gateway_impl::start(void)
-{
- _message.action = block_gw_message_type::ACTION_START;
- _handler->calleval(0);
- return _message.start_args_return_value;
-}
+ py::object ret = _py_handle.attr("stop")();
+ return ret.cast<bool>();
-bool block_gateway_impl::stop(void)
-{
- _message.action = block_gw_message_type::ACTION_STOP;
- _handler->calleval(0);
- return _message.stop_args_return_value;
}
-block_gw_message_type& block_gateway_impl::block_message(void) { return _message; }
-
} /* namespace gr */
diff --git a/gnuradio-runtime/lib/block_gateway_impl.h b/gnuradio-runtime/lib/block_gateway_impl.h
index a87f0ec1e5..168a78650e 100644
--- a/gnuradio-runtime/lib/block_gateway_impl.h
+++ b/gnuradio-runtime/lib/block_gateway_impl.h
@@ -1,6 +1,6 @@
/* -*- c++ -*- */
/*
- * Copyright 2013 Free Software Foundation, Inc.
+ * Copyright 2013,2020 Free Software Foundation, Inc.
*
* This file is part of GNU Radio
*
@@ -21,12 +21,10 @@ namespace gr {
class block_gateway_impl : public block_gateway
{
public:
- block_gateway_impl(feval_ll* handler,
+ block_gateway_impl(const py::handle& p,
const std::string& name,
gr::io_signature::sptr in_sig,
- gr::io_signature::sptr out_sig,
- const block_gw_work_type work_type,
- const unsigned factor);
+ gr::io_signature::sptr out_sig);
/*******************************************************************
* Overloads for various scheduler-called functions
@@ -38,23 +36,47 @@ public:
gr_vector_const_void_star& input_items,
gr_vector_void_star& output_items);
- int work(int noutput_items,
- gr_vector_const_void_star& input_items,
- gr_vector_void_star& output_items);
-
- int fixed_rate_noutput_to_ninput(int noutput_items);
- int fixed_rate_ninput_to_noutput(int ninput_items);
-
bool start(void);
bool stop(void);
+ void set_msg_handler_pybind(pmt::pmt_t which_port, std::string& handler_name)
+ {
+ if (msg_queue.find(which_port) == msg_queue.end()) {
+ throw std::runtime_error(
+ "attempt to set_msg_handler_pybind() on invalid input message port!");
+ }
+ d_msg_handlers_pybind[which_port] = handler_name;
+ }
+
+protected:
+ // Message handlers back into python using pybind API
+ typedef std::map<pmt::pmt_t, std::string, pmt::comparator> msg_handlers_pybind_t;
+ msg_handlers_pybind_t d_msg_handlers_pybind;
+
+ bool has_msg_handler(pmt::pmt_t which_port)
+ {
+ if (d_msg_handlers_pybind.find(which_port) != d_msg_handlers_pybind.end()) {
+ return true;
+ } else {
+ return gr::basic_block::has_msg_handler(which_port);
+ }
+ }
- block_gw_message_type& block_message(void);
+ void dispatch_msg(pmt::pmt_t which_port, pmt::pmt_t msg)
+ {
+ // Is there a handler?
+ if (d_msg_handlers_pybind.find(which_port) != d_msg_handlers_pybind.end()) {
+ // d_msg_handlers_pybind[which_port]->calleval(msg); // Yes, invoke it.
+ py::gil_scoped_acquire acquire;
+ // std::string handler_name(d_msg_handlers_pybind[which_port]);
+ py::object ret = _py_handle.attr(d_msg_handlers_pybind[which_port].c_str())(msg);
+ } else {
+ // Pass to generic dispatcher if not found
+ gr::basic_block::dispatch_msg(which_port, msg);
+ }
+ }
private:
- feval_ll* _handler;
- block_gw_message_type _message;
- const block_gw_work_type _work_type;
- unsigned _decim, _interp;
+ py::handle _py_handle;
};
} /* namespace gr */
diff --git a/gnuradio-runtime/lib/feval.cc b/gnuradio-runtime/lib/feval.cc
deleted file mode 100644
index 63e3fa419d..0000000000
--- a/gnuradio-runtime/lib/feval.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-/* -*- c++ -*- */
-/*
- * Copyright 2006,2013 Free Software Foundation, Inc.
- *
- * This file is part of GNU Radio
- *
- * SPDX-License-Identifier: GPL-3.0-or-later
- *
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <gnuradio/feval.h>
-
-namespace gr {
-
-feval_dd::~feval_dd() {}
-
-double feval_dd::eval(double x) { return 0; }
-
-double feval_dd::calleval(double x) { return eval(x); }
-
-// ----------------------------------------------------------------
-
-feval_cc::~feval_cc() {}
-
-gr_complex feval_cc::eval(gr_complex x) { return 0; }
-
-gr_complex feval_cc::calleval(gr_complex x) { return eval(x); }
-
-// ----------------------------------------------------------------
-
-feval_ll::~feval_ll() {}
-
-long feval_ll::eval(long x) { return 0; }
-
-long feval_ll::calleval(long x) { return eval(x); }
-
-// ----------------------------------------------------------------
-
-feval::~feval() {}
-
-void feval::eval(void)
-{
- // nop
-}
-
-void feval::calleval(void) { eval(); }
-
-// ----------------------------------------------------------------
-
-feval_p::~feval_p() {}
-
-void feval_p::eval(pmt::pmt_t x)
-{
- // nop
-}
-
-void feval_p::calleval(pmt::pmt_t x) { eval(x); }
-
-/*
- * Trivial examples showing C++ (transparently) calling Python
- */
-double feval_dd_example(feval_dd* f, double x) { return f->calleval(x); }
-
-gr_complex feval_cc_example(feval_cc* f, gr_complex x) { return f->calleval(x); }
-
-long feval_ll_example(feval_ll* f, long x) { return f->calleval(x); }
-
-void feval_example(feval* f) { f->calleval(); }
-
-} /* namespace gr */
diff --git a/gnuradio-runtime/python/gnuradio/gr/qa_feval.py b/gnuradio-runtime/python/gnuradio/gr/qa_feval.py
deleted file mode 100644
index 7018fd9f1a..0000000000
--- a/gnuradio-runtime/python/gnuradio/gr/qa_feval.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright 2006,2007,2010 Free Software Foundation, Inc.
-#
-# This file is part of GNU Radio
-#
-# SPDX-License-Identifier: GPL-3.0-or-later
-#
-#
-
-
-from gnuradio import gr, gr_unittest
-
-class my_add2_dd(gr.feval_dd):
- def eval(self, x):
- return x + 2
-
-class my_add2_ll(gr.feval_ll):
- def eval(self, x):
- return x + 2
-
-class my_add2_cc(gr.feval_cc):
- def eval(self, x):
- return x + (2 - 2j)
-
-class my_feval(gr.feval):
- def __init__(self):
- gr.feval.__init__(self)
- self.fired = False
- def eval(self):
- self.fired = True
-
-class test_feval(gr_unittest.TestCase):
-
- def test_dd_1(self):
- f = my_add2_dd()
- src_data = (0.0, 1.0, 2.0, 3.0, 4.0)
- expected_result = (2.0, 3.0, 4.0, 5.0, 6.0)
- # this is all in python...
- actual_result = tuple([f.eval(x) for x in src_data])
- self.assertEqual(expected_result, actual_result)
-
- def test_dd_2(self):
- f = my_add2_dd()
- src_data = (0.0, 1.0, 2.0, 3.0, 4.0)
- expected_result = (2.0, 3.0, 4.0, 5.0, 6.0)
- # this is python -> C++ -> python and back again...
- actual_result = tuple([gr.feval_dd_example(f, x) for x in src_data])
- self.assertEqual(expected_result, actual_result)
-
-
- def test_ll_1(self):
- f = my_add2_ll()
- src_data = (0, 1, 2, 3, 4)
- expected_result = (2, 3, 4, 5, 6)
- # this is all in python...
- actual_result = tuple([f.eval(x) for x in src_data])
- self.assertEqual(expected_result, actual_result)
-
- def test_ll_2(self):
- f = my_add2_ll()
- src_data = (0, 1, 2, 3, 4)
- expected_result = (2, 3, 4, 5, 6)
- # this is python -> C++ -> python and back again...
- actual_result = tuple([gr.feval_ll_example(f, x) for x in src_data])
- self.assertEqual(expected_result, actual_result)
-
-
- def test_cc_1(self):
- f = my_add2_cc()
- src_data = (0+1j, 2+3j, 4+5j, 6+7j)
- expected_result = (2-1j, 4+1j, 6+3j, 8+5j)
- # this is all in python...
- actual_result = tuple([f.eval(x) for x in src_data])
- self.assertEqual(expected_result, actual_result)
-
- def test_cc_2(self):
- f = my_add2_cc()
- src_data = (0+1j, 2+3j, 4+5j, 6+7j)
- expected_result = (2-1j, 4+1j, 6+3j, 8+5j)
- # this is python -> C++ -> python and back again...
- actual_result = tuple([gr.feval_cc_example(f, x) for x in src_data])
- self.assertEqual(expected_result, actual_result)
-
- def test_void_1(self):
- # this is all in python
- f = my_feval()
- f.eval()
- self.assertEqual(True, f.fired)
-
- def test_void_2(self):
- # this is python -> C++ -> python and back again
- f = my_feval()
- gr.feval_example(f)
- self.assertEqual(True, f.fired)
-
-
-if __name__ == '__main__':
- gr_unittest.run(test_feval, "test_feval.xml")