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 核心代码即可添加自定义功能
- 可以单独发布和分享
1.3 开发工具和资源
1.3.1 gr_modtool
gr_modtool 是模块编辑的瑞士军刀,它可以:- 自动编辑 makefiles
- 使用模板生成代码
- 处理繁琐的样板代码
- 让开发者直接专注于 DSP 编码
1.3.2 安装依赖
在 Ubuntu/Debian 系统上,安装 GNU Radio 后还需要以下包来编译 OOT 模块:
1.3.3 开发者资源
- Block Coding Guide - 块编码指南,包含命名规范
- Types of Blocks - 不同类型的块说明
- YAML GRC - YAML 格式的 GRC 块描述
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.yml1.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
- 在右侧的块列表中搜索你的块名称
- 或在分类
[My Module]下找到
- 将块拖到画布上使用
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
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 install 和 sudo 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 模块示例,实现一个简单的平方块。