Message passing as input and output in block (C++ coding)

Hi All,

I have another question about the message passing technique. In this
opportunity, I would like to create a block that takes message as input,
but also that post message downstream as output. In my initial attempt,
I’m
using the original blob_to_stream example (see below), the incoming
message
is taken using:

_msg = this->pop_msg_queue();

and then, in order to output the incoming message, it is used:

std::memcpy(output_items[0].get(), blob_mem, noutput_bytes);

However,

*(1) Is it possible to use an alternative way like this:

post_msg(0,_msg.key, _msg.value,_id); ?

*The goal is to output the same message to downstream.

Example blob to stream**************

int work(
const InputItems &input_items,
const OutputItems &output_items
){
//loop until we get a blob or interrupted
while (_offset == 0){
_msg = this->pop_msg_queue();
if (pmt::pmt_is_blob(_msg.value)) break;
}
if (pmt::pmt_blob_length(_msg.value) == 0) return -1; //empty
blob,
we are done here

    //calculate the number of bytes to copy
    const size_t nblob_items = (pmt::pmt_blob_length(_msg.value) -

_offset)/_item_size;
const size_t noutput_bytes =
_item_size*std::min<size_t>(output_items[0].size(), nblob_items);

    //perform memcpy from blob to output items
    const char *blob_mem = reinterpret_cast<const char

*>(pmt::pmt_blob_data(_msg.value)) + _offset;
std::memcpy(output_items[0].get(), blob_mem, noutput_bytes);

    //adjust the offset into the blob memory
    _offset += noutput_bytes;
    if (pmt::pmt_blob_length(_msg.value) == _offset) _offset = 0;

    return noutput_bytes/_item_size;
}

Thanks for your kind help,

Regards,

Jose.

On 10/07/2012 09:56 PM, Jose T. Diaz wrote:

and then, in order to output the incoming message, it is used:

std::memcpy(output_items[0].get(), blob_mem, noutput_bytes);

However,

*(1) Is it possible to use an alternative way like this:

post_msg(0,_msg.key, _msg.value,_id); ?

Yes, absolutely. This is the correct way to pass the message downstream.

-josh

Hi Josh,

Thanks for the info. So, for example if I want to modify the
blob_to_stream
example as blob_to_blob (ie. input a message and then output a message).
The .cc files is as shown below, but I got errors when I compile because
of
the type of variables:

In member function virtual int blob_to_blob_impl::work(const
InputItems&,
const OutputItems&):
/lib/blob_to_blob.cc:78:43: error: no matching function for call to
blob_to_blob_impl::post_msg(int, const pmt_t&, const char*&,
pmt::pmt_t&)
/lib/blob_to_blob.cc:78:43: note: candidates are:
/grextras/include/gnuradio/block.h:204:10: note: void
gnuradio::block::post_msg(size_t, const gr_tag_t&)
/grextras/include/gnuradio/block.h:204:10: note: candidate expects 2
arguments, 4 provided
/grextras/include/gnuradio/block.h:215:10: note: void
gnuradio::block::post_msg(size_t, const pmt_t&, const pmt_t&, const
pmt_t&)
/grextras/include/gnuradio/block.h:215:10: note: no known conversion
for
argument 3 from const char* to const pmt_t& {aka const
boost::intrusive_ptrpmt::pmt_base&}

The file blob_to_blob.cc is:

#include <gnuradio/extras/blob_to_blob.h>
#include <gr_io_signature.h>
#include //std::memcpy

using namespace gnuradio::extras;

static const pmt::pmt_t BLOB_KEY =
pmt::pmt_string_to_symbol(“blob_stream”); //From stream to blob

class blob_to_blob_impl : public blob_to_blob{
public:
blob_to_blob_impl(const size_t item_size):
block(
“blob_to_blob”,
gr_make_io_signature(0, 0, 0),
gr_make_io_signature(1, 1, item_size),
msg_signature(true, 1)
),
_item_size(item_size)
{
_offset = 0;

//From stream to blob example
std::stringstream str;
    str << name() << unique_id();
    _id = pmt::pmt_string_to_symbol(str.str());

}

int work(
    const InputItems &input_items,
    const OutputItems &output_items
){
    //Here the blob is received
    //loop until we get a blob or interrupted
    while (_offset == 0){
  _msg = this->pop_msg_queue(); //Reading the incoming blob
        if (pmt::pmt_is_blob(_msg.value)) break;
    }
    if (pmt::pmt_blob_length(_msg.value) == 0) return -1; //empty 

blob,
we are done here

    //calculate the number of bytes to copy
    const size_t nblob_items = (pmt::pmt_blob_length(_msg.value) -

_offset)/_item_size;
const size_t noutput_bytes =
_item_size*std::min<size_t>(output_items[0].size(), nblob_items);

    //perform memcpy from blob to output items
    const char *blob_mem = reinterpret_cast<const char

*>(pmt::pmt_blob_data(_msg.value)) + _offset;
//std::memcpy(output_items[0].get(), blob_mem, noutput_bytes);
//Putting in the output blob_mem

//post the message to downstream subscribers
    //this->post_msg(0, BLOB_KEY, blob, _id);
this->post_msg(0, BLOB_KEY, blob_mem, _id); //Using blob mem

    //adjust the offset into the blob memory
    _offset += noutput_bytes;
    if (pmt::pmt_blob_length(_msg.value) == _offset) _offset = 0;

    return noutput_bytes/_item_size;
}

private:
const size_t _item_size;
gr_tag_t _msg;
size_t _offset;
pmt::pmt_t _id; //From strem to blob example
};

blob_to_blob::sptr blob_to_blob::make(const size_t item_size){
return gnuradio::get_initial_sptr(new blob_to_blob_impl(item_size));
}

Many thanks again for your kind help,

Jose

Hi Josh,

I’ve figured out this question. I just need to post

this->post_msg(0,_msg);

Since, _msg is a gr_tag_t. But, still is not clear for me how can I post
a
message as follows:

this->post_msg(0, BLOB_METADATA,blob_data, _id); ?

I generated the BLOB_METADATA as pmt::pmt_t type. However, I cannot post
blob_data because is related to _msg (in the previous example), which is
a
gr_tag_t type.

If a copy this blob for example to a new blob as you suggested
previously,
can I then post using: this->post_msg(0, BLOB_METADATA,blob_data, _id);
?.
I mean, will it change to pmt_t type?.

Many thanks again,

Jose

On Tue, Oct 9, 2012 at 11:06 AM, Jose T. Diaz
<[email protected]

I generated the BLOB_METADATA as pmt::pmt_t type. However, I cannot post
blob_data because is related to _msg (in the previous example), which is a
gr_tag_t type.

There are two post_msg methods. The key/value version of the method is a
convenience method that makes a gr_tag_t and sets key and value

If a copy this blob for example to a new blob as you suggested previously,
can I then post using: this->post_msg(0, BLOB_METADATA,blob_data, _id); ?.
I mean, will it change to pmt_t type?.

The value parameter has to be type pmt::pmt_t

There is a function to create a blob from ptr and length:
http://gnuradio.org/cgit/gnuradio.git/tree/gruel/src/include/gruel/pmt.h#n330

-josh

Hi Josh,

I’ve checked this information and it is very useful. I’ve solved several
issues that I had before. However, it is still complaining when I post a
BLOB_METADATA (which is a pmt_list) downstream. What I have is the
following:

BLOCK 1 — > BLOCK 2 (both blocks use message passing as blobs)

In BLOCK 1 (work function):

while (_offset == 0){
_msg = this->pop_msg_queue(); //Reading the incoming blob
if (pmt::pmt_is_blob(_msg.value))
{
std::cout << std::endl << “found a blob in BLOCK 1” <<
std::endl;
break; }
}
if (pmt::pmt_blob_length(_msg.value) == 0)
{
std::cout << std::endl << “empty blob in BLOCK 1” << std::endl;
return -1;}

pmt::pmt_t BLOB_METADATA = pmt_list3(blob_key,blob_key2,blob_key3);
//For debugging
std::cout << std::endl << "Making a list" << std::endl;
std::cout << std::endl << "this is the list:" <<BLOB_METADATA<<

std::endl;

 this->post_msg(0,BLOB_METADATA,_msg.value,_id);  //BLOB_METADATA is 

a
list

In BLOCK 2 (work function):

while (_offset == 0){
_msg = this->pop_msg_queue(); //Reading the incoming blob
if (pmt::pmt_is_blob(_msg.value))
{
std::cout << std::endl << “found a blob in -BLOCK 2” <<
std::endl;
break; }
}
if (pmt::pmt_blob_length(_msg.value) == 0)
{
std::cout << std::endl << “empty blob in BLOCK 2” << std::endl;
return -1;} //empty blob, we are done here

this->post_msg(0,_msg); //Pass the message as it is

//For debugging
std::cout << std::endl << “posting a message downstream” <<
std::endl;
std::cout << std::endl << “DEBUG FROM BLOB TO BLOB 10/10” <<
std::endl;
std::cout << boost::format("value previous block=%8d, id previous
block=%16s ")
%_msg.value
%_msg.srcid

I’m passing a message from BLOCK 1 to BLOCK 2, then I changed the key
value
and I replaced it as a list (BLOB_METADATA). Everything is running, but
it
seems to be that the message is not passed from BLOCK 1 to BLOCK 2, here
is
my errors in GNU Radio Companion:
*
thread[thread-per-block[8]: <gr_block msg_sourcer (9)>]:
gr_block_detail::add_item_tag key: wrong_type : (st2_uplink
burst_start_key
burst_bb_gain)*

Note: st2_uplink burst_start_key burst_bb_gain is the value inside
blob1,
blob2 and blob3 in the list

Is there any restrictions passing a pmt_list from one block to another?,
or
is there any constraint when I read the incoming blob from BLOCK 1 into
BLOCK 2?.

Thanks a lot for your help,

Regards,

Jose

Hi Josh,

I’ve check the documentation and also my variables. I’ve found that my
list
is a PMT pair or PMT dict:

std::cout << std::endl << "checking if pair:"

<<pmt::pmt_is_pair(BLOB_METADATA)<< std::endl; //This gave me true
std::cout << std::endl << “checking if dict:”
<<pmt::pmt_is_dict(BLOB_METADATA)<< std::endl; //This gave me true

So, when I have to post the message downstream, I am using as follows:

this->post_msg(0,BLOB_METADATA,_msg.value,_id); //BLOB_METADATA is a
list

However, BLOB_METADATA should be symbol type (
http://gnuradio.org/doc/doxygen/classgr__block.html#a7578dece9d597abe61db91aae8a0df83).
In my case, it is a list which is PMT dict type.

Is there any way that I can post this list?, I mean, is there any way
that
I can convert PMT dict type into PMT symb type?.

Thanks for your help,

Jose.

On Wed, Oct 10, 2012 at 2:22 PM, Jose T. Diaz
<[email protected]