PMT blobs in Python

Hi,

can I convert a blob created by my C++ code (unsigned chars) to a Python
list or NumPy array?

pmt.blob_data() returns a ‘SwigPyObject’ with which I can’t do anything.
Passing it to a NumPy array constructor doesn’t seem to do the job.

The blobs are in a tuple:
pmt::pmt_t b1 = pmt::make_blob(a, a_length);
pmt::pmt_t b2 = pmt::make_blob(b, b_length);
return pmt::make_tuple(b1, b2);

And I try to check the contents of b1 in QA code like this:
res = my_test_function()
b1 = pmt.blob_data(pmt.tuple_ref(res, 0))
b1_len = pmt.blob_length(pmt.tuple_ref(res, 0))

Thanks,
Peter

I can’t really test this right now,
but you could insert
%include <cdata.i>
into your project’s swig file[1]; this should generate a python method
cdata(ptr, length)
that you can feed your blob_data() to. I’m not quite sure that WILL
work as is, maybe you will need a C(++) wrapper that simply returns
an array of known type (that is, int* instead of void*) that you can
yourself wrap into a SWIG array_class (like in the linked document).

Greetings
Marcus

[1] http://www.swig.org/Doc1.3/Library.html#Library_nn7

On second thought: Does using pmt.make_vector solve your problem?
in C++:
p = pmt::make_u8vector(length, fill);
(do stuff like pmt::u8vector_set(p, index, value), or even unsigned
char* p_vec = pmt::u8vector_writable_elements(p,length). The later can
summon hell if you use the same PMT object in multiple places.)

in python:
myvec= pmt.u8vector_elements§
Note, however, that this will inherently copy each individual uchar to a
python (long) int.

If you really want the raw bytes, you can always get really dependent
on PMT structure (which is basically fine, as long as you know that PMT
won’t change during the lifetime of your application), and use
pmt.serialize_str§
in python, as this will give you a string.

Thinking about that, there is yet another option, that suddendly blob’s
into mind.
in C++ , generate a std::string, and assign your char data to it:
std::string looks_like_it_s_text_but_is_data s();
s.assign(reinterpret_cast<const char*>(mydata), length);
pmt::pmt_t p = pmt::intern(s);

In python, you can use pmt.to_string§ to get back the string, in case
you want to use
it for a buffer.

PLEASE, be aware that this is NOT a good idea for high data volume or
high throughput;
string_to_symbol hashes the string, and saves the hash as well as the
pmt_t in a table.

On 08/04/2013 06:08 AM, Marcus M. wrote:

I can’t really test this right now,
but you could insert
%include <cdata.i>
into your project’s swig file[1]; this should generate a python method
cdata(ptr, length)
that you can feed your blob_data() to. I’m not quite sure that WILL
work as is, maybe you will need a C(++) wrapper that simply returns
an array of known type (that is, int* instead of void*) that you can
yourself wrap into a SWIG array_class (like in the linked document).

I dont know if this made it into PMT, buts its definitely in gr core for
the block gateway. Basically the snippet gives you a numpy array given a
ptr and length. Once its in numpy, you can shape it however, no copies
involved, do math on it, etc…

Here it is for the blob extensions in the old grextras:
https://github.com/guruofquality/grextras/blob/grextras_v3.6/python/extras_pmt.py#L32

Using a similar one in PMC to handle various numeric arrays:
https://github.com/guruofquality/PMC/blob/master/python/PMC/PMCNumericArray.i#L87

And again for the smart buffer type:
https://github.com/guruofquality/gras/blob/master/include/gras/sbuffer.i#L26

go numpy!

-josh