diff options
Diffstat (limited to 'gnuradio-core/src/python')
-rw-r--r-- | gnuradio-core/src/python/gnuradio/gr/gateway.py | 28 | ||||
-rw-r--r-- | gnuradio-core/src/python/gnuradio/gr/qa_python_message_passing.py | 123 |
2 files changed, 151 insertions, 0 deletions
diff --git a/gnuradio-core/src/python/gnuradio/gr/gateway.py b/gnuradio-core/src/python/gnuradio/gr/gateway.py index 244b8b592..c25755bb5 100644 --- a/gnuradio-core/src/python/gnuradio/gr/gateway.py +++ b/gnuradio-core/src/python/gnuradio/gr/gateway.py @@ -60,6 +60,24 @@ class gateway_handler(gr_core.feval_ll): return 0 ######################################################################## +# Handler that does callbacks from C++ +######################################################################## +class msg_handler(gr_core.feval_p): + + #dont put a constructor, it wont work + + def init(self, callback): + self._callback = callback + + def eval(self, arg): + try: self._callback(arg) + except Exception as ex: + print("handler caught exception: %s"%ex) + import traceback; traceback.print_exc() + raise ex + return 0 + +######################################################################## # The guts that make this into a gr block ######################################################################## class gateway_block(object): @@ -91,6 +109,9 @@ class gateway_block(object): self.__handler, name, gr_in_sig, gr_out_sig, work_type, factor) self.__message = self.__gateway.gr_block_message() + #dict to keep references to all message handlers + self.__msg_handlers = {} + #register gr_block functions prefix = 'gr_block__' for attr in [x for x in dir(self.__gateway) if x.startswith(prefix)]: @@ -171,6 +192,13 @@ class gateway_block(object): def start(self): return True def stop(self): return True + def set_msg_handler(self, which_port, handler_func): + handler = msg_handler() + handler.init(handler_func) + self.__gateway.set_msg_handler_feval(which_port, handler) + # Save handler object in class so it's not garbage collected + self.__msg_handlers[which_port] = handler + ######################################################################## # Wrappers for the user to inherit from ######################################################################## diff --git a/gnuradio-core/src/python/gnuradio/gr/qa_python_message_passing.py b/gnuradio-core/src/python/gnuradio/gr/qa_python_message_passing.py new file mode 100644 index 000000000..06bb96947 --- /dev/null +++ b/gnuradio-core/src/python/gnuradio/gr/qa_python_message_passing.py @@ -0,0 +1,123 @@ +#!/usr/bin/env python +# +# Copyright 2013 Free Software Foundation, Inc. +# +# This file is part of GNU Radio +# +# GNU Radio is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3, or (at your option) +# any later version. +# +# GNU Radio is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Radio; see the file COPYING. If not, write to +# the Free Software Foundation, Inc., 51 Franklin Street, +# Boston, MA 02110-1301, USA. +# + +from gnuradio import gr, gr_unittest +try: import pmt +except: from gruel import pmt +import numpy +import time + +# Simple block to generate messages +class message_generator(gr.sync_block): + def __init__(self, msg_list, msg_interval): + gr.sync_block.__init__( + self, + name = "message generator", + in_sig = [numpy.float32], + out_sig = None + ) + self.msg_list = msg_list + self.msg_interval = msg_interval + self.msg_ctr = 0 + self.message_port_register_out(pmt.pmt_intern('out_port')) + + + def work(self, input_items, output_items): + inLen = len(input_items[0]) + while self.msg_ctr < len(self.msg_list) and \ + (self.msg_ctr * self.msg_interval) < \ + (self.nitems_read(0) + inLen): + self.message_port_pub(pmt.pmt_intern('out_port'), + self.msg_list[self.msg_ctr]) + self.msg_ctr += 1 + return inLen + +# Simple block to consume messages +class message_consumer(gr.sync_block): + def __init__(self): + gr.sync_block.__init__( + self, + name = "message consumer", + in_sig = None, + out_sig = None + ) + self.msg_list = [] + self.message_port_register_in(pmt.pmt_intern('in_port')) + self.set_msg_handler(pmt.pmt_intern('in_port'), + self.handle_msg) + + def handle_msg(self, msg): + # Create a new PMT from long value and put in list + self.msg_list.append(pmt.pmt_from_long(pmt.pmt_to_long(msg))) + +class test_python_message_passing(gr_unittest.TestCase): + + def setUp(self): + self.tb = gr.top_block() + + def tearDown(self): + self.tb = None + + def test_000(self): + num_msgs = 10 + msg_interval = 1000 + msg_list = [] + for i in range(num_msgs): + msg_list.append(pmt.pmt_from_long(i)) + + # Create vector source with dummy data to trigger messages + src_data = [] + for i in range(num_msgs*msg_interval): + src_data.append(float(i)) + src = gr.vector_source_f(src_data, False) + msg_gen = message_generator(msg_list, msg_interval) + msg_cons = message_consumer() + + # Connect vector source to message gen + self.tb.connect(src, msg_gen) + + # Connect message generator to message consumer + self.tb.msg_connect(msg_gen, 'out_port', msg_cons, 'in_port') + + # Verify that the messgae port query functions work + self.assertEqual(pmt.pmt_symbol_to_string(pmt.pmt_vector_ref( + msg_gen.message_ports_out(), 0)), 'out_port') + self.assertEqual(pmt.pmt_symbol_to_string(pmt.pmt_vector_ref( + msg_cons.message_ports_in(), 0)), 'in_port') + + # Run to verify message passing + self.tb.start() + + # Wait for all messages to be sent + while msg_gen.msg_ctr < num_msgs: + time.sleep(0.5) + self.tb.stop() + self.tb.wait() + + # Verify that the message consumer got all the messages + self.assertEqual(num_msgs, len(msg_cons.msg_list)) + for i in range(num_msgs): + self.assertTrue(pmt.pmt_equal(msg_list[i], msg_cons.msg_list[i])) + +if __name__ == '__main__': + gr_unittest.run(test_python_message_passing, + 'test_python_message_passing.xml') |