From this conversation in the Perl 6 IRC channel and a question posted by Martin Barth, I'm trying to reproduce this C code using the Perl6 NativeCall interface, which is used with that purpose. This is what I have tried:
use NativeCall;
my uint32 $num = .new;
my num32 $float = .new: Num(1.0);
sub memcpy(num32 $float, uint32 $num, int32 $size) is native('Str') { * };
memcpy($float,$num,4);
say $num;
This yields an error:
This type cannot unbox to a native integer: P6opaque, Any
Which I interpret as, well, you have declared this as an Integer, I can't turn it into raw memory so that it can be copied from here to there.
This was only a possible way of answering the more general question by Martin Barth: how to turn raw bytes into a floating point number. Maybe there's other way of doing that, but in any case I'd be curious to find out how to turn C programs into NativeCall equivalents.
Update: in the meantime, here's the original question this other post tries to be a solution for.
Perl supports platform-native floating-point as scalar values; in practice this usually means IEEE 754 double precision. Exact Types. Perl can also store decimal numbers as strings, but the builtin arithmetic operators will convert them to integer or floating-point values to perform the operation.
How to parse binary data with Perl. 1 1. Open a binary filehandle. Start things off right by opening a filehandle to binary file: use autodie; open my $fh, '<:raw', ... 2 2. Read a few bytes. 3 3. Unpack bytes into variables.
Perl can also store decimal numbers as strings, but the builtin arithmetic operators will convert them to integer or floating-point values to perform the operation. The Math::BigFloat extension provides an arbitrary-precision decimal type:
Perl supports platform-native floating-point as scalar values; in practice this usually means IEEE 754 double precision. Perl can also store decimal numbers as strings, but the builtin arithmetic operators will convert them to integer or floating-point values to perform the operation.
Using a union (where all fields share the same memory space) is perhaps the most natural way. Declare a union like this:
my class Convertor is repr<CUnion> {
has uint32 $.i is rw;
has num32 $.n is rw;
}
And then use it to do conversion:
my $c = Convertor.new;
$c.i = 0b1000010111101101100110011001101;
say $c.n # 123.4000015258789
One other issue unrelated to the meat of the question, but present in the posted code: the native integer and number times never need to have a .new
done on them, because they are not object types. This:
my uint32 $num = .new;
Should just be:
my uint32 $num;
And:
my num32 $float = .new: Num(1.0);
Should just be:
my num32 $float = 1e0;
The use of the e
exponent is what makes a literal a float in Perl 6.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With