Polymorphic Types (PMTs)
- Introduction(介紹)
- More Complex Types(更復雜的資料型別)
- PMT Data Type(PMT資料型別)
- Inserting and Extracting Data(插入和提取資料)
- Strings(字串)
- Tests and Comparisons(測驗和比較)
- Dictionaries(資料字典)
- Vectors(向量型別)
- BLOB(BLOB型別物件)
- Pairs(對)
- Serializing and Deserializing(序列化和反序列化)
- Printing(列印)
- Collection Notation(集合符號)
- Conversion between Python Objects and PMTs(python物件與PMT物件的轉換)
Introduction(介紹)
Polymorphic Types are used as the carrier of data from one block/thread to another such as stream tags and message passing interfaces. PMT data types can represent a variety of data ranging from the Booleans to dictionaries. They are heavily used in the stream tags and message passing interfaces. In a sense, PMTs are a way to extend C++’ strict typing with something more flexible. The most complete list of PMT function is, of course, the source code, specifically the header file pmt.h. This page summarizes the most important features and points of PMTs.
多型資料型別通常用作從一個塊/執行緒到另一個塊/執行緒傳輸資料的載體,例如流標簽和訊息傳遞介面,PMT的資料型別可以表示各種各樣的資料,它們被大量的使用在流標簽和訊息傳遞介面中,從某種意義上來說,PMT用一種更靈活的方法去擴展了c++嚴格型別,最完整的PMT函式串列當然是源代碼,特別是頭檔案pmt.h,本頁總結了PMT最重要的特點以及要點,
Let’s dive straight into some Python code and see how we can use PMTs:
接下來讓我們直接通過python代碼來了解如何使用PMT,
>>> import pmt
>>> P = pmt.from_long(23)
>>> type(P)
<class 'pmt.pmt_swig.swig_int_ptr'>
>>> print P
23
>>> P2 = pmt.from_complex(1j)
>>> type(P2)
<class 'pmt.pmt_swig.swig_int_ptr'>
>>> print P2
0+1i
>>> pmt.is_complex(P2)
True
First, the pmt module is imported. We assign two values (P and P2) with PMTs using the from_long() and from_complex() calls, respectively. As we can see, they are both of the same type! This means we can pass these variables to C++ through SWIG, and C++ can handle this type accordingly.
首先,我們要匯入pmt模塊,我們使用form_long()函式和from_complex()函式來為PMTS(P 和 P2)來進行賦值,正如我們看到的,它們都是同樣的型別!這意味著我們可以通過swig將這些變數傳遞給c++語言,同時c++語言可以相應的處理這些型別的變更了,
The same code as above in C++ would look like this:
同樣的c++代碼如下所示:
#include <pmt/pmt.h>
// [...]
pmt::pmt_t P = pmt::from_long(23);
std::cout << P << std::endl;
pmt::pmt_t P2 = pmt::from_complex(gr_complex(0, 1));
// Alternatively: pmt::from_complex(0, 1)
std::cout << P2 << std::endl;
std::cout << pmt::is_complex(P2) << std::endl;
Two things stand out in both Python and C++: First, we can simply print the contents of a PMT. How is this possible? Well, the PMTs have in-built capability to cast their value to a string (this is not possible with all types, though). Second, PMTs must obviously know their type, so we can query that, e.g. by calling the is_complex() method.
PMT在python和c++的使用中有兩點突出:第一點,我們都能簡單的列印一個pmt型別的內容,為什么可以這樣操作呢?這是因為PMT又有一個可以將它們的值轉換為字串的內置功能(雖然這對于其他所有型別來說是不可能的)第二,PMT在使用的程序中必須清楚的知道它們自己的型別,所以我們可以進行查詢,例如通過is_complex()方法,
Note: When running the above as a standalone, the compiler command will look something like g++ pmt_tutorial.cpp -I$(gnuradio-config-info --prefix)/include -lgnuradio-pmt -o pmt_tutorial
注意:當我們獨立運行上述的代碼時,編譯器的指令看起來像:g++ pmt_tutorial.cpp -I$(gnuradio-config-info --prefix)/include -lgnuradio-pmt -o pmt_tutorial
When assigning a non-PMT value to a PMT, we can use the from_* methods, and use the to_* methods to convert back:
當我們將一個非PMT型別的值轉化為PMT型別時我們可以使用from_*方法,同時相反的我們可以使用to_*方法將PMT型別的值轉化為非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);
The last row shows the pmt::mp() shorthand function. It basically saves some typing, as it infers the correct from_ function from the given type.
代碼的最后一行展示了pmt::mp()速記函式的使用,它基本的節省了一些輸入,因為它可以通過給出的變數型別推測出正確的from_*()函式,
String types play a bit of a special role in PMTs, as we will see later, and have their own converter:
字串型別在PMT型別中扮演了一個非常重要的角色,在稍后我們會看到,并且它們有自己的轉換器,
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);
The pmt::intern is another way of saying pmt::string_to_symbol.
pmt::intern()是實作pmt::string_to_symbol()函式的另一種方法,
See the PMT docs and the header file pmt.h for a full list of conversion functions.
有關轉換函式的完整串列可以查看PMT的檔案以及頭檔案pmt.h
In Python, we can make use of the dynamic typing, and there’s actually a helper function to do these conversions (C++ also has a helper function for converting to PMTs called pmt::mp(), but it’s less powerful, and not quite as useful, because types are always strictly known in C++):
在python語言中我們可以使用動態資料型別,同時那里事實上還有一個輔助函式來實作型別轉換(c++同樣也有一個輔助函式用于PMT型別的轉換叫做pmt::mp(),但是它的功能不是那么的強大,也不是特別的實用,因為在c++中資料型別一幫都是嚴格已知的):
P_int = pmt.to_pmt(42)
i = pmt.to_python(P_int)
P_double = pmt.to_pmt(0.2)
d = pmt.to_double(P_double)
On a side note, there are three useful PMT constants, which can be used in both Python and C++ domains. In C++, these can be used as such:
附帶說明一下,這里有三個非常有用的PMT常量,它們都可以在python和c++域中使用,例如在c++中是這樣使用的:
pmt::pmt_t P_true = pmt::PMT_T;
pmt::pmt_t P_false = pmt::PMT_F;
pmt::pmt_t P_nil = pmt::PMT_NIL;
在python中是這樣使用的:
pmt::pmt_t P_true = pmt::PMT_T;
pmt::pmt_t P_false = pmt::PMT_F;
pmt::pmt_t P_nil = pmt::PMT_NIL;
pmt.PMT_T and pmt.PMT_F are boolean PMT types representing True and False, respectively. The PMT_NIL is like a NULL or None and can be used for default arguments or return values, often indicating an error has occurred.
pmt.PMT_T和pmt.PMT_F是布爾型別的變數分別表示true和false,PMT_NIL就類似于NULL或者None型別的變數并且常用于默認引數和回傳值,通常表示發生了某個錯誤,
To be able to go back to C++ data types, we need to be able to find out the type from a PMT. The family of is_* methods helps us do that:
為了能夠回到c++資料型別,我們需要找出PMT的資料型別,一系列的is_*()方法可以幫我們實作,
double d;
if (pmt::is_integer(P)) {
d = (double) pmt::to_long(P);
} else if (pmt::is_real(P)) {
d = pmt::to_double(P);
} else {
// We really expected an integer or a double here, so we don't know what to do
throw std::runtime_error("expected an integer!");
}
It is important to do type checking since we cannot unpack a PMT of the wrong data type.
進行資料型別的檢查是非常重要的,因為我們不能解壓一個錯誤資料型別的PMT,
We can compare PMTs without knowing their type by using the pmt::equal() function:
我們能可以利用pmt::equal()函式在不知道PMT資料型別的情況下進行比較,
if (pmt::eq(P_int, P_double)) {
std::cout << "Equal!" << std::endl; // This line will never be reached
There are more equality functions, which compare different things: pmt::eq() and pmt::eqv(). We won’t need these for this tutorial.
這里有更多的相同作用的函式用來比較不同的資料型別,例如pmt::eq()以及pmt::eqv()函式,本次教程不需要這些
The rest of this page provides more depth into how to handle different data types with the PMT library.
本頁剩余的部分將更深入的介紹如何使用PMT庫處理不同的資料型別,
More Complex Types(更復雜的資料型別)
PMTs can hold a variety of types. Using the Python method pmt.to_pmt(), we can convert most of Pythons standard types out-of-the-box:
PMT能容納多種的資料型別,利用python方法中的pmt.to_pmt()函式,我們能夠轉換大多數的python標準型別開箱即用,
P_tuple = pmt.to_pmt((1, 2, 3, 'spam', 'eggs'))
P_dict = pmt.to_pmt({'spam': 42, 'eggs': 23})
But what does this mean in the C++ domain? Well, there are PMT types that define tuples and dictionaries, keys and values being PMTs, again.
但是這在c++中意味著什么呢?好的,這里有PMT型別定義的元組和字典,鍵值和值也都是PMT型別,
So, to create the tuple from the Python example, the C++ code would look like this:
所以,要像python那樣創建元組,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"))
For the dictionary, it’s a bit more complex:
對于資料字典,它會稍微有點復雜:
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));
As you can see, we first need to create a dictionary, then assign every key/value pair individually.
正如你所看到的,我們首先需要創建一個資料字典,然后各自為它們賦值鍵值對的值,
A variant of tuples are vectors. Like Python’s tuples and lists, PMT vectors are mutable, whereas PMT tuples are not. In fact, PMT vectors are the only PMT data types that are mutable. When changing the value or adding an item to a dictionary, we are actually creating a new PMT.
元組的一個變體是向量,就像python中的元組和串列,PMT向量是可變的,但是PMT元組是不可變的,事實上,PMT向量是PMT資料型別中唯一可變的型別,當我們改變字典中的值或者向字典中添加元素時,我們實際上創造了一個新的PMT,
To create a vector, we can initialize it to a certain lengths, and fill all elements with an initial value. We can then change items or reference them:
創建一個向量,我們可以初始化給它一個確定的長度,并且用一個值來初始化所有的元素,然后我們可以改變元素或者參考它們,
pmt::pmt_t P_vector = pmt::make_vector(5, pmt::from_long(23)); // Creates a vector with 5 23's as PMTs
pmt::vector_set(P_vector, 0, pmt::from_long(42)); // Change the first element to a 42
std::cout << pmt::vector_ref(P_vector, 0); // Will print 42
In Python, we can do all these steps (using pmt.make_vector() etc.), or convert a list:
在python中,我們可以執行所有的步驟(使用pmt.make_vector()方法等等),或者轉換一個串列:
P_vector = pmt.to_pmt([42, 23, 23, 23, 23])
Vectors are also different from tuples in a sense that we can directly load data types into the elements, which don’t have to be PMTs.
從某種意義來講向量不同于元組,例如我們可以直接向元組中加入不是PMT資料型別的元素,
Say we want to pass a series of 8 float values to another block (these might be characteristics of a filter, for example). It would be cumbersome to convert every single element to and from PMTs, since all elements of the vector are the same type.
假設我們想傳輸大量的8位浮點數的值到另一個塊(例如,這可能是一個過濾器的特點),將每一個元素都與PMT型別進行轉換會變得很麻煩,因為向量中的所有元素都是同一個型別,
We can use special vector types for this case:
對于這種情況,我們可以使用特殊的向量型別:
pmt::pmt_t P_f32vector = pmt::make_f32vector(8, 5.0); // Creates a vector with 8 5.0s's as floats
pmt::f32vector_set(P_f32vector, 0, 2.0); // Change the first element to a 2.0
float f = f32vector_ref(P_f32vector, 0);
std::cout << f << std::endl; // Prints 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; // Prints all elements from P_f32vector, one after another
Python has a similar concept: Numpy arrays. As usual, the PMT library understands this and converts as expected:
python中也有類似的概念:Numpy arrays,像往常一樣,PMT庫明白這一點并按預期進行轉換:
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'
Here, ‘f32’ stands for ‘float, 32 bits’. PMTs know about most typical fixed-width data types, such as ‘u8’ (unsigned 8-bit character) or ‘c32’ (complex with 32-bit floats for each I and Q). Consult the manual for a full list of types.
這里,‘f32’代表32位的浮點數,PMT知道大多數典型固定寬度的資料型別,例如‘u8’(8位無符號字符)或者‘c32’(對于每個I和Q都具有32位浮點數),有關型別的詳細串列,請看參考手冊,
The most generic PMT type is probably the blob (binary large object). Use this with care - it allows us to pass around anything that can be represented in memory.
最通用的PMT型別大概是blob型別(binary large object二進制大物件),注意小心使用:它可以傳遞任何可以在記憶體中表示的資料,
PMT Data Type(PMT資料型別)
All PMTs are of the type pmt::pmt_t. This is an opaque container and PMT functions must be used to manipulate and even do things like compare PMTs. PMTs are also immutable (except PMT vectors). We never change the data in a PMT; instead, we create a new PMT with the new data. The main reason for this is thread safety. We can pass PMTs as tags and messages between blocks and each receives its own copy that we can read from. However, we can never write to this object, and so if multiple blocks have a reference to the same PMT, there is no possibility of thread-safety issues of one reading the PMT data while another is writing the data. If a block is trying to write new data to a PMT, it actually creates a new PMT to put the data into. Thus we allow easy access to data in the PMT format without worrying about mutex locking and unlocking while manipulating them.
所有的PMT都用pmt::pmt_t來表示,這是一個不透明的容器并且必須使用PMT型別函式來進行操作和比較,PMT同樣是不可變的(除了PMT向量),我們從來補改變PMT中的資料;相反的我們根據新的資料創建新的PMT,主要的原因是我們要保證執行緒安全,我們可以像標簽和資訊一樣在塊與塊之間傳遞PMT資料,并且每個接收塊我們可以從接收器中讀取接收的資訊,但是我們永遠無法寫入此物件,因此,如果多個塊參考同一個PMT,由于執行緒安全,我們不可能從同時在一個對一個PMT讀取和寫入資料,如果一個塊嘗試寫入新的資料到PMT,事實上它創建了一個新的PMT來寫入資料我們可以輕松的訪問PMT中的資料而不用在操作時擔心互斥鎖和解鎖問題,
PMTs can represent the following:
PMT可以表示如下的資料型別
Boolean values of true/false
Strings (as symbols)
Integers (long and uint64)
Floats (as doubles)
Complex (as two doubles)
Pairs
Tuples
Vectors (of PMTs)
Uniform vectors (of any standard data type)
Dictionaries (list of key:value pairs)
Any (contains a boost::any pointer to hold anything)
The PMT library also defines a set of functions that operate directly on PMTs such as:
PMT同時還定義了一系列可以直接操作PMT的函式,如下:
Equal/equivalence between PMTs
Length (of a tuple or vector)
Map (apply a function to all elements in the PMT)
Reverse
Get a PMT at a
position in a list
Serialize and deserialize
Printing
The constants in the PMT library are:
PMT庫中的常量如下:
pmt::PMT_T - a PMT True
pmt::PMT_F - a PMT False
pmt::PMT_NIL - an empty PMT (think Python’s ‘None’)
Inserting and Extracting Data(插入和提取資料)
Use pmt.h for a complete guide to the list of functions used to create PMTs and get the data from a PMT. When using these functions, remember that while PMTs are opaque and designed to hold any data, the data underneath is still a C++ typed object, and so the right type of set/get function must be used for the data type.
通過使用頭檔案pmt.h來得到用于創建PMT的函式串列以及從pmt得到資料,當我們使用這些函式的時候要注意,盡管PMT是不透明的并且用于儲存各種資料,但是下面的資料型別依舊是c++物件,所以對于不同的資料型別必須選用合適型別的set/get函式,
Typically, a PMT object can be made from a scalar item using a call like pmt::from_<type>. Similarly, when getting data out of a PMT, we use a call like “pmt::to_”. For example:
通常,可以使用一個一個類似形如pmt::from_<type>的方法來創建PMT物件,類似的,當我們從PMT物件中獲取資料時,我們可以使用一個形如pmt::to_<type>的方法來實作,例如:
double a = 1.2345;
pmt::pmt_t pmt_a = pmt::from_double(a);
double b = pmt::to_double(pmt_a);
int c = 12345;
pmt::pmt_t pmt_c = pmt::from_long(c);
int d = pmt::to_long(pmt_c);
As a side-note, making a PMT from a complex number is not obvious:
需要注意的是,從一個使用復數來創建PMT是不明顯的,
std::complex<double> a(1.2, 3.4);
pmt::pmt_t pmt_a = pmt::make_rectangular(a.real(), a.imag());
std::complex<double> b = pmt::to_complex(pmt_a);
Pairs, dictionaries, and vectors have different constructors and ways to manipulate them, and these are explained in their own sections.
對,字典以及向量都有著不同的建構式和方法去使用它們,這些都在它們自己的庫中有著解釋,
Strings(字串)
PMTs have a way of representing short strings. These strings are actually stored as interned symbols in a hash table, so in other words, only one PMT object for a given string exists. If creating a new symbol from a string, if that string already exists in the hash table, the constructor will return a reference to the existing PMT.
PMT有一種方法來表示短的字串,這些字串實際上作為內部符號儲存在哈希表中,所以換句話說對于一個字串只有一個包含該字串的PMT物件存在,如果為一個字串創建一個物件,如果發現該字串已經存在在哈希表中了,建構式會回傳一個指向存在
We create strings with the following functions, where the second function, pmt::intern, is simply an alias of the first.
我們通過下面的函式來創建字串,這里的第二個函式pmt::intern只是第一個函式的別名,
pmt::pmt_t str0 = pmt::string_to_symbol(std::string("some string"));
pmt::pmt_t str1 = pmt::intern(std::string("some string"));
The string can be retrieved using the inverse function:
我們同樣可以使用相反型別的函式來得到字串,
std::string s = pmt::symbol_to_string(str0);
Tests and Comparisons(測驗和比較)
The PMT library comes with a number of functions to test and compare PMT objects. In general, for any PMT data type, there is an equivalent pmt::is_<type>. We can use these to test the PMT before trying to access the data inside. Expanding our examples above, we have:
PMT庫包含了大量的函式來測驗和比較PMT物件,一般來說,對于任意的PMT資料型別,都有一個與之對應的函式pmt::_is<type>,我們可以在我們獲取PMT里面存放的資料之前來檢測資料型別,擴展上面的例子我們可以得到:
pmt::pmt_t str0 = pmt::string_to_symbol(std::string("some string"));
if(pmt::is_symbol(str0))
std::string s = pmt::symbol_to_string(str0);
double a = 1.2345;
pmt::pmt_t pmt_a = pmt::from_double(a);
if(pmt::is_double(pmt_a))
double b = pmt::to_double(pmt_a);
int c = 12345;
pmt::pmt_t pmt_c = pmt::from_long(c);
if(pmt::is_long(pmt_a))
int d = pmt::to_long(pmt_c);
\\ This will fail the test. Otherwise, trying to coerce \b pmt_c as a
\\ double when internally it is a long will result in an exception.
if(pmt::is_double(pmt_a))
double d = pmt::to_double(pmt_c);
Dictionaries(資料字典)
PMT dictionaries are lists of key:value pairs. They have a well-defined interface for creating, adding, removing, and accessing items in the dictionary. Note that every operation that changes the dictionary both takes a PMT dictionary as an argument and returns a PMT dictionary. The dictionary used as an input is not changed and the returned dictionary is a new PMT with the changes made there.
PMT字典是鍵值對的串列,它們都有一個定義好的介面用來創建,增加,洗掉以及獲取字典中的專案,注意,每個改變資料字典的操作都需要用PMT作為引數并且回傳值也是一個PMT資料字典,被用作輸入的資料字典并沒有改變,同時回傳的資料字典也是一個新的修改的PMT物件,
The following is a list of PMT dictionary functions. View each function in the GNU Radio C++ Manual to get more information on what each does.
下面列出了一系列的字典函式,查看GNU Radio C++手冊中的每個函式可以得到它們的功能的更詳細介紹,
bool pmt::is_dict(const pmt_t &obj)
pmt_t pmt::make_dict()
pmt_t pmt::dict_add(const pmt_t &dict, const pmt_t &key, const pmt_t &value)
pmt_t pmt::dict_delete(const pmt_t &dict, const pmt_t &key)
bool pmt::dict_has_key(const pmt_t &dict, const pmt_t &key)
pmt_t pmt::dict_ref(const pmt_t &dict, const pmt_t &key, const pmt_t ¬_found)
pmt_t pmt::dict_items(pmt_t dict)
pmt_t pmt::dict_keys(pmt_t dict)
pmt_t pmt::dict_values(pmt_t dict)
This example does some basic manipulations of PMT dictionaries in Python. Notice that we pass the dictionary a and return the results to a. This still creates a new dictionary and removes the local reference to the old dictionary. This just keeps our number of variables small.
此示例在python語言中對PMT字典做了一些基本的操作,注意我們傳遞了字典a同時回傳了結果到字典a,這同樣創建了一個新的字典同時對舊字典的本地參考,這只是保持我們的變數數比較小,
import pmt
key0 = pmt.intern("int")
val0 = pmt.from_long(123)
val1 = pmt.from_long(234)
key1 = pmt.intern("double")
val2 = pmt.from_double(5.4321)
# Make an empty dictionary
a = pmt.make_dict()
# Add a key:value pair to the dictionary
a = pmt.dict_add(a, key0, val0)
print a
# Add a new value to the same key;
# new dict will still have one item with new value
a = pmt.dict_add(a, key0, val1)
print a
# Add a new key:value pair
a = pmt.dict_add(a, key1, val2)
print a
# Test if we have a key, then delete it
print pmt.dict_has_key(a, key1)
a = pmt.dict_delete(a, key1)
print pmt.dict_has_key(a, key1)
ref = pmt.dict_ref(a, key0, pmt.PMT_NIL)
print ref
# The following should never print
if(pmt.dict_has_key(a, key0) and pmt.eq(ref, pmt.PMT_NIL)):
print "Trouble! We have key0, but it returned PMT_NIL"
Vectors(向量型別)
PMT vectors come in two forms: vectors of PMTs and vectors of uniform data. The standard PMT vector is a vector of PMTs, and each PMT can be of any internal type. On the other hand, uniform PMTs are of a specific data type which come in the form:
PMT向量有兩種形式組成:PMT向量和統一資料型別向量,標準PMT向量是一個由多個PMT物件組成的向量,每個PMT可以是任何內部型別,另一方面,統一型別的PMT具有特定的資料型別,主要有一下幾種型別:
(u)int8
(u)int16
(u)int32
(u)int64
float32
float64
complex 32 (std::complex<float>)
complex 64 (std::complex<double>)
That is, the standard sizes of integers, floats, and complex types of both signed and unsigned.
也就是說,標準大小的整數、浮點數以及復數型別都包括有符號和無符號的,
Vectors have a well-defined interface that allows us to make, set, get, and fill them. We can also get the length of a vector with pmt::length, or in Python:
向量組有一個定義好的介面允許我們去創建、設定、獲取和填充它們,在c++中我們同樣可以通過方法pmt::length來得到向量組的長度,或者在python中像下面一樣得到:
pmt_t p1 = pmt_integer(1);
pmt_t p2 = pmt_integer(2);
pmt_t p3 = pmt_integer(3);
pmt_t p_list = pmt_list3(p1, p2, p3);
pmt_length(p_list); // Returns 3
For standard vectors, these functions look like:
對于標準向量組,它們的函式如下所示:
bool pmt::is_vector(pmt_t x)
pmt_t pmt::make_vector(size_t k, pmt_t fill)
pmt_t pmt::vector_ref(pmt_t vector, size_t k)
void pmt::vector_set(pmt_t vector, size_t k, pmt_t obj)
void pmt::vector_fill(pmt_t vector, pmt_t fill)
Uniform vectors have the same types of functions, but they are data type-dependent. The following list tries to explain them where you substitute the specific data type prefix for \a dtype (prefixes being: u8, u16, u32, u64, s8, s16, s32, s64, f32, f64, c32, c64).
同一型別向量的函式具有相同格式,取決于給函式的引數資料型別,下面的串列嘗試來解釋它們在哪個位置替換合適的資料型別前綴(前綴可以是:u8, u16, u32, u64, s8, s16, s32, s64, f32, f64, c32, c64)
bool pmt::is_(dtype)vector(pmt_t x)
pmt_t pmt::make_(dtype)vector(size_t k, (dtype) fill)
pmt_t pmt::init_(dtype)vector(size_t k, const (dtype*) data)
pmt_t pmt::init_(dtype)vector(size_t k, const std::vector<dtype> data)
pmt_t pmt::(dtype)vector_ref(pmt_t vector, size_t k)
void pmt::(dtype)vector_set(pmt_t vector, size_t k, (dtype) x)
const dtype* pmt::(dtype)vector_elements(pmt_t vector, size_t &len)
dtype* pmt::(dtype)vector_writable_elements(pmt_t vector, size_t &len)
List of available pmt::is_(dtype)vector(pmt_t x) methods from pmt.h:
一系列的有效方法pmt::is(dtype)vector(pmt_x)都在pmt.h頭檔案中:
bool pmt::is_uniform_vector()
bool pmt::is_u8vector()
bool pmt::is_s8vector()
bool pmt::is_u16vector()
bool pmt::is_s16vector()
bool pmt::is_u32vector()
bool pmt::is_s32vector()
bool pmt::is_u64vector()
bool pmt::is_s64vector()
bool pmt::is_f32vector()
bool pmt::is_f64vector()
bool pmt::is_c32vector()
bool pmt::is_c64vector()
Note: We break the contract with vectors. The ‘set’ functions actually change the data underneath. It is important to keep track of the implications of setting a new value as well as accessing the ‘vector_writable_elements’ data. Since these are mostly standard data types, sets and gets are atomic, so it is unlikely to cause a great deal of harm. But it’s only unlikely, not impossible. Best to use mutexes whenever manipulating data in a vector.
注意:我們違反了向量的規定,‘set’函式實際上改變了下面的資料,跟蹤設定新值的影響和獲得’vector_writable_elements’的資料都很重要,因為這些大多數是標準的資料型別,set和get函式也是在內核中,所以也不太可能導致比較大的危害性,但是只是可能性比較低,并不是不可能的,最好在操作向量中的資料時使用資料鎖,
BLOB(BLOB型別物件)
A BLOB is a ‘binary large object’ type. In PMT’s, this is actually just a thin wrapper around a u8vector.
BLOB資料型別是‘二進制大小物件’型別,在PMT中,它實際上只是一個圍繞u8vector的一個薄包裝,
Pairs(對)
A concept that originates in Lisp dialects are pairs and cons. The simplest explanation is just that: If you combine two PMTs, they form a new PMT, which is a pair (or cons) of those two PMTs (don’t worry about the weird name, a lot of things originating in Lisp have weird names. Think of a ‘construct’).
一個來自Lisp編程語言的概念是pairs和cons,最通俗易懂的解釋就是:如果你要組合兩個PMT物件成一個新的PMT物件,它們就是一個pairs或者cons(不要在意奇怪的名字,很多起源于Lisp語言的名字都很奇怪)
Similarly to vectors or tuples, pairs are a useful way of packing several components of a message into a single PMT. Using the PMTs generated in the previous section, we can combine two of these to form a pair, here in Python:
類似于vectors和tuples,pairs也是一個很有效的方法來實作把幾個資訊的部分打包到一個PMT物件中,使用上一節生成的PMT物件,我們可以把它們兩兩組成一個物件,下面用python實作:
P_pair = pmt.cons(pmt.string_to_symbol("taps"), P_f32vector)
print pmt.is_pair(P_pair) # Prints 'true'
You can combine PMTs as tuples, dictionaries, vectors, or pairs, it’s just a matter of taste. This construct is well-established though, and as such used in GNU Radio quite often.
你可以將PMT組成一個tuple、字典、vector或者pairs,看你自己想怎么做了,目前這種結構已經很成熟了,因此在GNU Radio經常被使用,
So how do we deconstruct a pair? That’s what the car and cdr functions do. Let’s deconstruct that previous pair in C++:
但是我們如何拆散一個pairs呢?這就是car和cdr函式所要做的,讓我們先來用c++實作拆散之前的pairs:
pmt::pmt_t P_key = pmt::car(P_pair);
pmt::pmt_t P_f32vector2 = pmt::cdr(P_pair);
std::cout << P_key << std::endl; // Will print 'taps' using the PMT automatic conversion to strings
Here is a summary of the pairs-related functions in C++ and Python:
這里是一些有關pairs函式的總結,有c++和python語言:
bool pmt::is_pair(const pmt_t &obj): Return true if obj is a pair, else false
pmt_t pmt::cons(const pmt_t &x, const pmt_t &y): construct new pair
pmt_t pmt::car(const pmt_t &pair): get the car of the pair (first object)
pmt_t pmt::cdr(const pmt_t &pair): get the cdr of the pair (second object)
void pmt::set_car(pmt_t pair, pmt_t value): Stores value in the car field
void pmt::set_cdr(pmt_t pair, pmt_t value): Stores value in the cdr field
And in Python we have:
python實作方法:
pmt.is_pair(pair_obj) # Return True if is a pair, else False (warning: also returns True for a dict)
pmt.cons(x, y) # Return a newly allocated pair whose car is x and whose cdr is y
pmt.car(pair_obj) # If is a pair, return the car, otherwise raise wrong_type
pmt.cdr(pair_obj) # If is a pair, return the cdr, otherwise raise wrong_type
pmt.set_car(pair_obj, value) # Store value in car field
pmt.set_cdr(pair_obj, value) # Store value in cdr field
For more advanced pair manipulation, refer to the documentation and the Wikipedia page for car and cdr.
對于更詳細的pair操作方法,參考car 和 cdr的檔案和維基百科頁面,
Serializing and Deserializing(序列化和反序列化)
It is often important to hide the fact that we are working with PMTs to make them easier to transmit, store, write to file, etc. The PMT library has methods to serialize data into a string buffer or a string and then methods to deserialize the string buffer or string back into a PMT. We use this extensively in the metadata files (see Metadata Information).
隱藏我們正在使用的PMT使得它們更容易傳輸、存盤以及寫入檔案等操作這很重要,PMT庫具有將資料序列化到字串緩沖區和字串的方法,同樣的也有將字串緩沖區或字串轉發回到PMT的方法,我們在元資料檔案上廣泛使用它(詳情請看元資料資訊)
bool pmt::serialize(pmt_t obj, std::streambuf &sink)
std::string pmt::serialize_str(pmt_t obj)
pmt_t pmt::deserialize(std::streambuf &source)
pmt_t pmt::deserialize_str(std::string str)
For example, we will serialize the data above to make it into a string ready to be written to a file and then deserialize it back to its original PMT.
例如,我們將序列化上面的資料成一個字符準備寫入檔案然后在通過反序列化將檔案轉化為原始的PMT,
import pmt
key0 = pmt.intern("int")
val0 = pmt.from_long(123)
key1 = pmt.intern("double")
val1 = pmt.from_double(5.4321)
# Make an empty dictionary
a = pmt.make_dict()
# Add a key:value pair to the dictionary
a = pmt.dict_add(a, key0, val0)
a = pmt.dict_add(a, key1, val1)
print a
ser_str = pmt.serialize_str(a)
print ser_str
b = pmt.deserialize_str(ser_str)
print b
The line where we ‘print ser_str’ will print and parts will be readable, but the point of serializing is not to make a human-readable string. This is only done here as a test.
在‘print ser_str’這一行字串ser_str將被列印并且是可讀的,但是序列化的重點不是得到一個人們可讀的字串,這只是作為一個測驗,
Printing(列印)
In Python, the __repr__ function of a PMT object is overloaded to call pmt::write_string. This means that any time we call a formatted printing operation on a PMT object, the PMT library will properly format the object for display.
在python語言中,PMT物件中的__repr__函式被多載用來呼叫pmt::write_string函式,這意味著在任何時候我們對一個PMT物件呼叫格式化列印操作時,PMT庫都會正確格式化該物件并顯示,
In C++, we can use the ‘pmt::print(object)’ function or print the contents is using the overloaded “<<” operator with a stream buffer object. In C++, we can inline print the contents of a PMT like:
在c++中,我們可以使用pmt::print(object)函式來列印或者用多載的‘<<’運算子和流緩沖區物件來列印內容,在c++中,我們可以像下面這樣來進行試試列印PMT中的內容:
pmt::pmt_t a = pmt::from_double(1.0);
std::cout << "The PMT a contains " << a << std::endl;
Collection Notation(集合符號)
PMTs use a different bracket notation from what one might be use to in Python.
PMT使用一種與在python中不同的集合表示符,
>>> my_dict
((meaning . 42))
>>> my_vector
#[1 2 3 4]
>>> pmt.make_tuple(pmt.from_long(321), pmt.from_float(3.14))
{321 3.14}
>>> pmt.cons(pmt.from_long(1), pmt.from_long(2))
(1 . 2)
>>> my_pdu
(() . #[1 2 3 4])
Conversion between Python Objects and PMTs(python物件與PMT物件的轉換)
Although PMTs can be manipulated in Python using the Python versions of the C++ interfaces, there are some additional goodies that make it easier to work with PMTs in python. There are functions to automate the conversion between PMTs and Python types for booleans, strings, integers, longs, floats, complex numbers, dictionaries, lists, tuples and combinations thereof.
雖然可以使用python版本中的c++介面在python來操作PMT物件,但是還有一些額外的好處使得在python中更簡單的使用PMT物件,這里有一些自動轉換PMT物件和python基本型別的函式包括:用于布林值、字串、整數、長整數、浮點數、復數、字典、串列、元組及其組合,
Two functions capture most of this functionality:
下面兩個函式包含了大部分功能:
pmt.to_pmt # Converts a python object to a PMT.
pmt.to_python # Converts a PMT into a python object.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/290739.html
標籤:其他
