GRC C++ Generation: Difference between revisions

From GNU Radio
Jump to navigation Jump to search
mNo edit summary
Line 1: Line 1:
Note: This page is a work in progress.
Starting from GNU Radio 3.8, GRC allows you to generate C++ code (not just Python) from your flowgraph. This feature was a SOCIS (ESA Summer of Code in Space) project in 2017. The C++ generation mode is significantly less stable and feature-rich than the default Python mode, since Python is a far more flexible language (and since GRC was created to generate Python code). About 50% of the in-tree blocks support C++ generation. The C++ generation templates have to be written on a per-block basis, which is a considerable amount of work. This also means that it is a considerable amount of work to keep the C++ templates updated, which is why some blocks' templates may be outdated and produce errors. The good news is that these errors often have trivial fixes.
Starting from GNU Radio 3.8, GRC allows you to generate C++ code (not just Python) from your flowgraph. This feature was a SOCIS (ESA Summer of Code in Space) project in 2017. The C++ generation mode is significantly less stable and feature-rich than the default Python mode, since Python is a far more flexible language (and since GRC was created to generate Python code). About 50% of the in-tree blocks support C++ generation. The C++ generation templates have to be written on a per-block basis, which is a considerable amount of work. This also means that it is a considerable amount of work to keep the C++ templates updated, which is why some blocks' templates may be outdated and produce errors. The good news is that these errors often have trivial fixes.


Line 9: Line 7:
* CMakeLists.txt
* CMakeLists.txt


All of these files are generated from templates, and changes in your flowgraph will be reflected in them. Additionally, GRC creates a build directory which you can call cmake and make from. Pressing the execute button in GRC will generate, compile and run your flowgraph. However, it is often convenient to compile and run your flowgraph in a separate terminal.
All of these files are generated from templates, and changes in your flowgraph will be reflected in them. Additionally, GRC creates a build directory which you can call cmake and make from. Pressing the execute button in GRC will generate, compile and run your flowgraph. However, it is often convenient to compile and run your flowgraph in a separate terminal. C++ output for a flowgraph can be enabled by changing the Output Language parameter of the Options block from Python to C++ and pressing OK. That's all, given that the blocks in your flowgraph support C++ output.  


== Adding C++ Templates to a Block ==


== Adding C++ Templates to a Block ==
'''Note:''' C++ generation requires that the block's implementation is written in C++, which most blocks are. However, some blocks are purely written in Python, and these can't produce C++ code. You might want to use a different block.


This guide builds on the [https://wiki.gnuradio.org/index.php?title=Creating_c%2B%2B_OOT_with_gr-modtool C++ OOT guide]. The steps listed here will fall between [https://wiki.gnuradio.org/index.php?title=Creating_c%2B%2B_OOT_with_gr-modtool#Modifying_the_YAML_.yml_File Modifying the YAML file] and [https://wiki.gnuradio.org/index.php?title=Creating_c%2B%2B_OOT_with_gr-modtool#Compiling_and_Installing_the_Block Compiling_and_Installing_the_Block].  
Some blocks don't have C++ templates yet. However, adding C++ templates is often quite simple. This guide builds on the [https://wiki.gnuradio.org/index.php?title=Creating_c%2B%2B_OOT_with_gr-modtool C++ OOT guide]. The steps listed here will fall between [https://wiki.gnuradio.org/index.php?title=Creating_c%2B%2B_OOT_with_gr-modtool#Modifying_the_YAML_.yml_File Modifying the YAML file] and [https://wiki.gnuradio.org/index.php?title=Creating_c%2B%2B_OOT_with_gr-modtool#Compiling_and_Installing_the_Block Compiling_and_Installing_the_Block].  


In order to enable C++ generation for our multDivSelect block, we need to add some additional lines to the YAML file (comments have been removed for brevity):
In order to enable C++ generation for our multDivSelect block, we need to add some additional lines to the YAML file (comments have been removed for brevity):
Line 62: Line 61:


=== Generation Issues ===
=== Generation Issues ===
==== Generate Error: (NameError("(...) is not defined") ====
This error is actually not C++-specific. It appears if you use a variable that is not defined, this is usually caused by typos. In the context of the multDiv block, the following line would cause a NameError:
<syntaxhighlight lang="c++">
cpp_templates:
(...)
  make: 'this->${id} = customModule::multDivSelect::make(${selllector});'
(...)
</syntaxhighlight>


==== This block does not support C++ output ====
==== This block does not support C++ output ====
Line 92: Line 102:


GRC will do a search and replace operation on your block's generated code, replacing all instances of True and False with true and false, respectively.
GRC will do a search and replace operation on your block's generated code, replacing all instances of True and False with true and false, respectively.
==== undefined reference to (...) ====
There is something missing in the target_link_libraries() call in your flowgraph's CMakeLists.txt. Your block YAML's link field is probably incorrect. Try gnuradio::gnuradio-qtgui (in-tree blocks) or gnuradio-customModule (OOT blocks). Replace qtgui or customModule with the actual module's name.


=== Runtime Issues ===
=== Runtime Issues ===

Revision as of 21:15, 14 August 2022

Starting from GNU Radio 3.8, GRC allows you to generate C++ code (not just Python) from your flowgraph. This feature was a SOCIS (ESA Summer of Code in Space) project in 2017. The C++ generation mode is significantly less stable and feature-rich than the default Python mode, since Python is a far more flexible language (and since GRC was created to generate Python code). About 50% of the in-tree blocks support C++ generation. The C++ generation templates have to be written on a per-block basis, which is a considerable amount of work. This also means that it is a considerable amount of work to keep the C++ templates updated, which is why some blocks' templates may be outdated and produce errors. The good news is that these errors often have trivial fixes.

GRC generates C++ code by creating a new directory with three files:

  • top_block.cpp
  • top_block.hpp
  • CMakeLists.txt

All of these files are generated from templates, and changes in your flowgraph will be reflected in them. Additionally, GRC creates a build directory which you can call cmake and make from. Pressing the execute button in GRC will generate, compile and run your flowgraph. However, it is often convenient to compile and run your flowgraph in a separate terminal. C++ output for a flowgraph can be enabled by changing the Output Language parameter of the Options block from Python to C++ and pressing OK. That's all, given that the blocks in your flowgraph support C++ output.

Adding C++ Templates to a Block

Note: C++ generation requires that the block's implementation is written in C++, which most blocks are. However, some blocks are purely written in Python, and these can't produce C++ code. You might want to use a different block.

Some blocks don't have C++ templates yet. However, adding C++ templates is often quite simple. This guide builds on the C++ OOT guide. The steps listed here will fall between Modifying the YAML file and Compiling_and_Installing_the_Block.

In order to enable C++ generation for our multDivSelect block, we need to add some additional lines to the YAML file (comments have been removed for brevity):

id: customModule_multDivSelect
label: multDivSelect
category: '[customModule]'
flags: [cpp]

templates:
  imports: from gnuradio import customModule
  make: customModule.multDivSelect(${selector})

cpp_templates:
  includes: ['#include <gnuradio/customModule/multDivSelect.h>']
  declarations: 'customModule::multDivSelect::sptr ${id};'
  link: ['gnuradio-customModule']
  make: 'this->${id} = customModule::multDivSelect::make(${selector});'
  translations:
    'True': 'true'
    'False': 'false'

parameters:
- id: selector
  label: Selector, Multiply (true) or Divide (false)
  dtype: bool
  default: true

inputs:
- label: in0
  domain: stream
  dtype: complex
- label: in1
  domain: stream
  dtype: complex
outputs:
- label: out0
  domain: stream
  dtype: complex

file_format: 1

The translations field might not be necessary for your block, it is used here to de-capitalize the boolean selector parameter. Next, you can follow the C++ OOT guide (e.g. cmake, make, make install) to compile the module. Once this has been done, you can load the updated block information into GRC by pressing the Reload Blocks button or restarting GRC.

Troubleshooting

Generation Issues

Generate Error: (NameError("(...) is not defined")

This error is actually not C++-specific. It appears if you use a variable that is not defined, this is usually caused by typos. In the context of the multDiv block, the following line would cause a NameError:

cpp_templates:
(...)
  make: 'this->${id} = customModule::multDivSelect::make(${selllector});'
(...)

This block does not support C++ output

The block does not have the cpp flag set, which can be found near the start of the YAML file (line 4 in the example above). This usually means that the block does not have C++ templates either. You can try writing the templates yourself, or create an issue on Github and ask for someone else to do it.

Compilation Issues

‘True’ was not declared in this scope

Consolidate compiler generated dependencies of target cpptest
[ 50%] Building CXX object CMakeFiles/cpptest.dir/cpptest.cpp.o
/home/hkon/oot/gr-customModule/build/cpptest/cpptest.cpp: In constructor cpptest::cpptest():
/home/hkon/oot/gr-customModule/build/cpptest/cpptest.cpp:37:80: error: True was not declared in this scope
   37 |         this->customModule_multDivSelect_0 = customModule::multDivSelect::make(True);
      |                                                                                ^~~~
make[2]: *** [CMakeFiles/cpptest.dir/build.make:90: CMakeFiles/cpptest.dir/cpptest.cpp.o] Error 1

In C++, the boolean type is either true or false (lowercase), while the corresponding Python type is True or False. Try adding a translations field to the cpp_templates:

cpp_templates:
  (...)
  translations:
    'True': 'true'
    'False': 'false'

GRC will do a search and replace operation on your block's generated code, replacing all instances of True and False with true and false, respectively.

undefined reference to (...)

There is something missing in the target_link_libraries() call in your flowgraph's CMakeLists.txt. Your block YAML's link field is probably incorrect. Try gnuradio::gnuradio-qtgui (in-tree blocks) or gnuradio-customModule (OOT blocks). Replace qtgui or customModule with the actual module's name.

Runtime Issues