GNURadio中的PMTs(Polymorphic Types)数据类型

目录

1、整体概述

2、使用方法的举例说明

3、对于PMT类型的补充说明


1、整体概述

PMTs在GNURadio中代表多态类型(Polymorphic Types),这种类型不像float、int一样是严格意义上的数据类型,更像是为了模块间信息传输的方便而对不同的数据类型进行统一的包装(在GR模块中,相互之间的数据传输必须是同一种数据类型)。该数据类型可以用来存储任何类型的数据,并且可以简单地转换为常见的数据类型,如bool、long、vector等,常用于流标签(stream tags)以及数据传送接口(message passing )中。当所有的数据都定义为pmt类型时,由于数据具有相同的类型,大大简化了GR块之间的数据传输。

2、使用方法的举例说明

下面是一些简单的李子来说明pmt数据的作用。

首先是一般的定义方式(Python):

import pmt
# 定义pmt数据
p1 = pmt.from_long(23)
print("type of p1:",type(p1))
print(p1)
# 定义pmt数据p2
p2 = pmt.from_complex(1j)
print("type of p2:", type(p2))
print(p2)
print("Is p2 a complex?:", pmt.is_complex(p2))
# 在不确定原始数据类型的情况下,is_*可以用来精确的恢复原始数据类型
if pmt.is_complex(p2):
    d = pmt.to_complex(p2)
elif pmt.is_integer(p2):
    d = pmt.to_long(p2)
else: # 抛出异常
    raise ValueError("expected an integer or complex")

'''  运行结果  
type of p1: <class 'pmt.pmt_swig.swig_pmt_ptr'>
23
type of p2: <class 'pmt.pmt_swig.swig_pmt_ptr'>
0+1i
Is p2 a complex?: True
'''

上述代码首先定义了pmt类型数据p1和p2,分别将一个整型数据和一个复数型数据转换为pmt类型。我们可以打印出p1和p2的数据类型可以发现都是pmt.pmt_swig.swig_pmt_ptr类型,但是打印出来后仍然是各自原始类型的形式,这是由于在打印时,pmt是将原类型的数据转化为字符串输出。另我们可以调用类似is_complex()的方法来查询pmt数据的原始数据类型。在不确定原始数据类型的情况下,is_*方法可以用来精确的恢复原始数据类型。

下面是c++版本的定义方式:

#include "iostream"
#include "pmt/pmt.h"
int main()
{
    // long型数据转化为pmt型
    pmt::pmt_t p1 = pmt::from_long(23);
    // 打印该pmt数据,结果仍是23
    std::cout << "p1: " << p1 << std::endl;
    // 复数(0+1j)转化为pmt型
    pmt::pmt_t p2 =pmt::from_complex(0, 1);
    // 同样的,结果仍是0+1j
    std::cout << "p2: " << p2 << std::endl;
    // 验证P2是否仍是复数,结果为1(true)
    std::cout << "is p2 a complex?: " << pmt::is_complex(p2) << std::endl;
    return 0;
}

/*   运行结果
p1: 23
p2: 0+1i
is p2 a complex?: 1
*/

在terminal中输入指令 g++ test.cpp -lgnuradio-pmt -o test来进行编译,输入./test来运行。实际命令需要根据实际情况进行修改。

当将一个非pmt数据转化为pmt数据时,可以使用from_*方法,反过来可以使用to_*的方法将pmt数据转换回来

pmt::pmt_t P_int = pmt::from_long(42);
int i = pmt::to_long(P_int);
pmt::pmt_t P_double = pmt::from_double(0.2);
double d = pmt::to_double(P_double);
pmt::pmt_t P_double = pmt::mp(0.2);

pmt::mp是一种简写方式,可以从给定的数据中自动推断出正确的from_类型并转化为pmt

类似于pmt::mp,在Python中也可以使用动态转化方法pmt.to_pmt。另外pytohn中多了一个动态恢复的函数pmt.to_python,自动获取pmt数据的原始类型并恢复。

p_int = pmt.to_pmt(42)
i = pmt.to_python(p_int)
print("i: ", i, "type of i: ", type(i))
p_double = pmt.to_pmt(42.0)
d = pmt.to_double(p_double)
print("d: ", d, "type of d: ", type(d))

'''  运行结果
i:  42 type of i:  <class 'int'>
d:  42.0 type of d:  <class 'float'>
'''

另外,在pmt中有三个常用的常量(python版)

P_true = pmt.PMT_T
P_false = pmt.PMT_F
P_nil = pmt.PMT_NIL

以上三中数据类型分别代表布尔pmt类型的true、false,以及NULL或者None, 可用来做默认参数或者返回值等。c++中的定义于python类似。

字符串类型在PMTs中有着重要的作用

pmt::pmt_t P_str = pmt::string_to_symbol("spam");
pmt::pmt_t P_str2 = pmt::intern("spam");
std::string str = pmt::symbol_to_string(P_str);

pmt::intern方法的作用同pmt::string_to_symbol,同上文提到的pmt::mp一样,也是一种简写方式。

其他一些复杂数据类型的定义就一起写在下面供参考(Python版):

# 元组类型的转换
P_tuple = pmt.to_pmt((1, 2, 3, 'spam', 'eggs'))
# 字典类型的转换
P_dict = pmt.to_pmt({'spam': 42, 'eggs': 23})
# np数组的转化
P_f32vector = pmt.to_pmt(numpy.array([2.0, 5.0, 5.0, 5.0, 5.0], dtype=numpy.float32))
print pmt.is_f32vector(P_f32vector) # Prints 'True'

c++版本的要稍微复杂一些:

 对于c++创建字典类型的pmt,需要首先创建一个字典,然后分别添加每一个键值对

pmt::pmt_t P_dict = pmt::make_dict();
P_dict = pmt::dict_add(P_dict, pmt::string_to_symbol("spam"), pmt::from_long(42));
P_dict = pmt::dict_add(P_dict, pmt::string_to_symbol("eggs"), pmt::from_long(23));

对于元组类型,c++代码如下:

pmt::pmt_t P_tuple = pmt::make_tuple(pmt::from_long(1), pmt::from_long(2), pmt::from_long(3), pmt::string_to_symbol("spam"), pmt::string_to_symbol("eggs"))

对于向量来说,可以先初始化一个使用初始值进行填充的确定长度的向量,然后可以对其进行数据修改。

// 创建一个含有五个视觉,每个数据都是23的向量
pmt::pmt_t P_vector = pmt::make_vector(5, pmt::from_long(23)); 
// 将第一个数据改为42
pmt::vector_set(P_vector, 0, pmt::from_long(42)); 
// 打印结果将是 42
std::cout << pmt::vector_ref(P_vector, 0); 

在c++的元组定义中可以发现,元组内的数据类型必须全部转化为pmt。而向量不同于元组,我们可以在向量中直接载入非pmt类型的数据。比如,我们想传送8个float型(比如,这些数据可以是一个滤波器的一些参数)的数据到另一个模块,而将每个元素与 PMT 相互转换会很麻烦,这时我们可以使用如下所示的特殊向量类型:

// 创建一个含有8个值为5.0的float数据的pmt向量,注意这里float数据无需转换为pmt类型
pmt::pmt_t P_f32vector = pmt::make_f32vector(8, 5.0); 
pmt::f32vector_set(P_f32vector, 0, 2.0); // 将第一个元素赋值为2.0
float f = f32vector_ref(P_f32vector, 0);
std::cout << f << std::endl; // 打印结果为 2.0
size_t len;
float *fp = pmt::f32vector_elements(P_f32vector, len);
for (size_t i = 0; i < len; i++)
    std::cout << fp[i] << std::endl; // 一词打印P_f32vector中的所有元素

3、对于PMT类型的补充说明

PMT数据在程序中的数据类型为:pmt::pmt_t。除上文提到的pmt vectors类型外,pmt类型的数据都不可改变,相当于只读的。主要原因是考虑到线程安全的问题,这样就不会发生在一个线程(模块)读pmt数据的同时另一个线程也在修改该pmt数据的线程安全问题,事实上,我们写数据到PMT中的操作自始至终都是一个创建新的pmt数据的过程。

参考:Polymorphic Types (PMTs) - GNU Radio

  • 1
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

地球被支点撬走啦

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值