Reputation: 23527
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.
Upvotes: 9
Views: 196
Reputation: 29454
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.
Upvotes: 9