Friday, October 12, 2012

Understanding a Singal Processing Block in GNU Radio : SWIG Interface : Naming Conventions

Download the file gr-howto-write-a-block-3.3.0.tar.gz from

Naming convention for block names :

After we create our block the only way we can use it in GNU Radio is to create a python script which loads the package/module containing the our block, and then connect our block to the GNU Radio flow graph

It will be something like this :

from package_name import module_name

new_block = module_name.block_name()

There is an important key coupling between the module and block names which we invoke in python, and the names used in the coding blocks of C++

GNU Radio expects that all the C++ source and header files are in the form [module_name]_[block_name].h  and [module_name]_[block_name].cc

Hence if we decided to name our C++ class as newModule_newBlock, then GNU Radio's build system would make our block available from python in module "newModule" and with block name "newBlock"

Naming convention for boost smart pointers :

All pointers to the GNU Radio blocks must use boost shared pointers and not the regular C++ pointers

If we create a new C++ signal processing block  called "newModule_newBlock" then GNU Radio's internal implementation will not work if we use a regular C++ pointer to newBlock_newFunction in our code

In other words the command

newModule_newBlock* ptr newBlock_newFunction() wont work in GNU Radio

This rule is enforced by making all the block constructors private and ensures that a regular C++ pointer can never point to a block object

But if the constructor is private, how do we create new instance of our block , after all we need some pubic interface for creating new block instances

The solution is to declare a friend function !!

This is done by first declaring a friend function of the class, so that it has access to all the private members of the class including the private constructor

This friend function invokes the private constructor and returns a smart pointer to it 

We invoke this friend function everytime we want to construct a new object of the class

Suppose the name of our new signal processing block is newModule_newBlock_cc , then we would create a file , in which we would include the following function declaration :

typedef boost::shared_ptr newModule_newBlock_cc_sptr

friend newModule_newBlock_cc_sptr newModule_make_newBlock_cc()

Now the function newModule_make_newBlock_cc has access to the private members of the class newModule_newBlock_cc

The final step is to cast the return pointer's data type from raw C++ pointer to a smart pointer

newModule_newBlock_cc_sptr newModule_make_newBlock_cc() () {
   return newModule_newBlock_cc_sptr (new newModule_newBlock_cc());

By the way the private constructor which can be invoked directly is some thing like as follows :

newModule_newBlock_cc() {
            gr_makeio_signature (1,1, sizeof (gr_complex)),
            gr_make_iosignature (1,1, sizeof (gr_complex))

So to summarize, the private constructor is actually creating a new gr_block object

The "friend constructor" which is the public interface to the private constructor
, acts as a surrogate by wrapping the new object created by the private constructor into a boost shared pointer

This complex procedure ensures that all the pointers to the block are boost smart pointers

The public interface for creating objects is actually not the  object constructor newModule_newBlock_cc but rather the "surrogate" constructor newModule_make_newBlock_cc

So in our code we must use the following code to create a new block object nb :

newModule_newBlock_cc_sptr nb = newModule_make_newBlock_cc()

One important point to be mentioned here : if one's block name is newModule_newBlock_cc then the name of the shared pointer to this block MUST be newModule_newBlock_cc_sptr

Any other choice would lead to code not working properly

The above naming  has nothing to do with the C++ , but when this C++ block is invoked from python in a GNU Radio program , GNU Radio expects the name of shared pointer to follow directly from the block name with an appended _sptr to it, or else it will complain that it couldn't find the block

Also the surrogate constructor which creates a shared pointer to newModue_newBlock_cc must have signature

newModule_newBlock_cc_sptr newModule_make_newBlock_cc()

*Note the presence of the word make between newModule and newBlock

Reference :

No comments:

Post a Comment