Subject: passing binary data from c extension back to ruby
Date: ven 21 feb 14 11:58:00 +0100
Quoting Kape K. ([email protected]):
I see there is rb_str_new2(char*) but the data is not null terminated on
the c side so I’m hesitant to use that conversion function.
As you already could read, you can use rb_str_new, and pass to it the
pointer to your data and length in bytes. This function will generate
a String object, which includes length information (no need to rely on
null-termination, thus). From Ruby, pass it to Socket#write, and all
your bytes will be transmitted, without mangling.
You can also manipulate binary data in a String from ruby using
String#unpack and Array#pack. Say that your data contains three
short unsigned integers (16bit), two signed longs (32bit) and a double
(64bit) - thus, 22 bytes. You can do
array=string.unpack(‘SSSlld’)
and you will find in your array the six values. Array#pack does the
reverse:
string=[12,23,34,1010101,-332211,3.1415].pack(‘SSSlld’)
p string.bytes
gives
[12, 0, 23, 0, 34, 0, 181, 105, 15, 0, 77, 238, 250, 255, 111, 18, 131,
192, 202, 33, 9, 64]
Everything works smoothly as long as your string does not use a
multibyte
encoding. The default encoding for Ruby strings is UTF-8, but strings
generated by rb_str_new and Array#pack have ASCII-8BIT encoding.
Type
ri Array#pack
to know more.
Carlo