type
Post
status
Published
date
Mar 30, 2026
slug
grcoot
summary
tags
数字通信
coding
category
数字通信
icon
password
上次编辑时间
Mar 30, 2026 09:07 AM
AI summary

1 GNU Radio C++ OOT 开发指南

1.1 目录

  • 1. OOT 模块简介
  • 2. 开发工具和资源
  • 3. 创建 OOT 模块
  • 4. 模块结构
  • 5. 创建 C++ Block
  • 6. Block 类型
  • 7. 编译和安装
  • 8. 在 GRC 中使用
  • 9. 常见问题和技巧

1.2 OOT 模块简介

1.2.1 什么是 OOT 模块?

OOT (Out-Of-Tree) 模块是不位于 GNU Radio 源码树中的 GNU Radio 组件。如果你想用自己的功能和模块扩展 GNU Radio,OOT 模块就是需要创建的内容。
OOT 模块的优势:
  • 可以自行维护代码
  • 与主代码并存提供额外功能
  • 无需修改 GNU Radio 核心代码即可添加自定义功能
  • 可以单独发布和分享
许多 OOT 项目托管在 CGRAN (Comprehensive GNU Radio Archive Network)。

1.3 开发工具和资源

1.3.1 gr_modtool

gr_modtool 是模块编辑的瑞士军刀,它可以:
  • 自动编辑 makefiles
  • 使用模板生成代码
  • 处理繁琐的样板代码
  • 让开发者直接专注于 DSP 编码

1.3.2 安装依赖

在 Ubuntu/Debian 系统上,安装 GNU Radio 后还需要以下包来编译 OOT 模块:

1.3.3 开发者资源


1.4 创建 OOT 模块

1.4.1 使用 gr_modtool 创建新模块

这将创建一个名为 gr-my_module 的新目录。

1.4.2 模块创建输出示例


1.5 模块结构

创建的模块包含以下子目录:

1.5.1 目录说明

  • lib/:C++ 或 C 源代码
  • include/:C++ 头文件(需要导出的 API)
  • python/:Python 模块、单元测试
  • swig/:SWIG 绑定说明(让 C++ 块在 Python 中可用)
  • grc/:GRC 块描述文件(3.8+ 使用 YAML,之前是 XML)
  • docs/:文档(使用 Doxygen 和 Sphinx)
  • apps/:完整的应用程序
  • examples/:使用示例

1.6 创建 C++ Block

1.6.1 添加新 Block

在模块目录中执行:

1.6.2 Block 类型选择

gr_modtool 会询问块类型:
主要类型说明:
  • sink:只有输入,没有输出
  • source:只有输出,没有输入
  • sync:同步块,输入输出数量相同
  • decimator:抽取器,输出数量少于输入
  • interpolator:插值器,输出数量多于输入
  • general:通用块,完全自定义行为
  • tagged_stream:带标签流的块
  • hier:分层块(由其他块组成)

1.6.3 选择语言和参数

1.6.4 生成的文件

执行后会生成/修改以下文件:

1.7 Block 类型详解

1.7.1 Sync Block(同步块)

同步块是最常见的类型。对于每个输入项,产生相同数量的输出项。
工作原理
  • 消耗的输入项 = noutput_items
  • 产生的输出项 = noutput_items
适用场景
  • 元素级的数学运算(乘、加、滤波器等)
  • 一对一转换
示例

1.7.2 Decimator Block(抽取块)

输出项数少于输入项数。
工作原理
  • 消耗 ninput_items 个输入
  • 产生 noutput_items = floor(ninput_items / decimation) 个输出
适用场景
  • 下采样
  • 降采样
示例

1.7.3 Interpolator Block(插值块)

输出项数多于输入项数。
工作原理
  • 消耗 noutput_items / interpolation 个输入
  • 产生 noutput_items 个输出
适用场景
  • 上采样
  • 升采样

1.7.4 Source Block(源块)

只有输出,没有输入。
适用场景
  • 信号生成器
  • 数据源(文件、网络等)
示例

1.7.5 Sink Block(宿块)

只有输入,没有输出。
适用场景
  • 数据显示
  • 文件写入
  • 数据发送

1.7.6 General Block(通用块)

完全自定义行为,需要实现更多函数。
需要实现的函数
  • forecast(): 预测需要的输入
  • general_work(): 通用工作函数

1.8 实现 C++ Block

1.8.1 修改头文件 (my_block_impl. h)

1.8.2 修改实现文件 (my_block_impl. cc)

1.8.3 work 函数详解

work() 函数是信号处理的核心,参数说明:
参数
  • noutput_items:请求的输出项数
  • input_items:输入项的指针数组(每个输入端口一个)
  • output_items:输出项的指针数组(每个输出端口一个)
返回值
  • 实际产生的输出项数
重要提示
  • 永远不要返回大于 noutput_items 的值
  • 可以返回小于 noutput_items 的值(如果处理失败或需要更多信息)
  • 对于同步块,通常返回 noutput_items

1.9 修改 YAML GRC 文件

1.9.1 YAML 文件位置

grc/my_module_my_block.block.yml

1.9.2 完整 YAML 文件示例

1.9.3 YAML 文件关键字段

字段
说明
id
块的唯一标识符(格式:module_blockname)
label
在 GRC 中显示的名称
category
GRC 中的分类
templates.imports
Python 导入语句
templates.make
创建块的 Python 代码
parameters
可设置的参数列表
inputs
输入端口列表
outputs
输出端口列表
dtype
数据类型(int, float, complex, byte, short 等)

1.10 编译和安装

1.10.1 构建流程

1.10.2 遇到问题时的清理

1.10.3 重新编译

修改代码后:

1.11 在 GRC 中使用

1.11.1 启动 GRC

1.11.2 查找自定义 Block

  1. 在右侧的块列表中搜索你的块名称
  1. 或在分类 [My Module] 下找到
  1. 将块拖到画布上使用

1.11.3 测试流程图

创建一个简单的测试流程图:

1.12 单元测试

1.12.1 Python QA 代码

添加块时选择 Add Python QA code? [Y/n]: Y 会自动生成测试框架。
python/qa_my_block. py:

1.12.2 运行测试


1.13 高级主题

1.13.1 设置历史(History)

对于需要访问历史数据的块:

1.13.2 预测(Forecast)

对于通用块,需要预测需要的输入:

1.13.3 设置输出倍数(Output Multiple)

强制输出项数为某个数的倍数:

1.13.4 消息传递

添加消息端口:

1.14 调试技巧

1.14.1 使用 GDB

设置断点:

1.14.2 日志输出

使用 GNU Radio 的日志系统:

1.14.3 性能分析

使用 gr_time_perfect_square 示例或自定义计时器。

1.15 发布和分享

1.15.1 创建 PyBOMBS 配方

创建 PyBOMBS 配方文件,让其他人可以通过 PyBOMBS 安装。

1.15.2 提交到 CGRAN

将你的模块提交到 CGRAN 与社区分享。

1.15.3 版本控制

使用 Git 管理你的代码:

1.16 参考资源

1.16.1 官方文档

1.16.2 社区资源

  • CGRAN - Comprehensive GNU Radio Archive Network

1.16.3 示例项目

  • gr- blocks in GNU Radio source tree
  • CGRAN 上的各种 OOT 模块

1.17 常见问题(FAQ)

1.17.1 Q1: gr_modtool 找不到命令

A: 确保 gnuradio-dev 已安装并正确配置了 PATH。

1.17.2 Q2: 编译时找不到 gnuradio 头文件

A: 确保 gnuradio-dev 已安装,并且 CMake 能找到 GNU Radio。

1.17.3 Q3: GRC 中找不到我的块

A: 确保已执行 sudo make installsudo ldconfig,然后重启 GRC。

1.17.4 Q4: 运行时出现 "undefined symbol"

A: 通常是链接问题,检查 CMakeLists. txt 中的库依赖。

1.17.5 Q5: 如何使用复数类型?

A: 使用 gr_complex 类型,它是 std::complex<float> 的别名。

1.18 附录 A: 完整示例

以下是一个完整的 C++ OOT 模块示例,实现一个简单的平方块。

1.18.1 square_block_impl. h

1.18.2 square_block_impl. cc

1.18.3 YAML 配置文件