В Perl 6, как я могу преобразовать необработанные байты в число с плавающей запятой, используя интерфейс NativeCall? - PullRequest
0 голосов
/ 29 апреля 2018

Из этого разговора в IRC-канале Perl 6 и вопроса, опубликованного Мартином Бартом, я пытаюсь воспроизвести этот код C с использованием интерфейса Perl6 NativeCall, который используется с этой целью. Вот что я пробовал:

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 type cannot unbox to a native integer: P6opaque, Any

Который я интерпретирую как, ну, вы объявили это как целое число, я не могу превратить его в сырую память, чтобы его можно было скопировать отсюда туда.

Это был только возможный способ ответить на более общий вопрос Мартина Барта: как превратить необработанные байты в число с плавающей запятой. Возможно, есть другой способ сделать это, но в любом случае мне было бы любопытно узнать, как превратить программы на C в эквиваленты NativeCall.

Обновление : тем временем вот оригинальный вопрос, который этот пост пытается решить для .

1 Ответ

0 голосов
/ 29 апреля 2018

Использование объединения (где все поля занимают одно и то же пространство памяти) является, пожалуй, наиболее естественным способом. Объявите союз так:

my class Convertor is repr<CUnion> {
    has uint32 $.i is rw;
    has num32 $.n is rw;
}

А затем используйте его для преобразования:

my $c = Convertor.new;
$c.i = 0b1000010111101101100110011001101;
say $c.n  # 123.4000015258789

Еще одна проблема, не относящаяся к сути вопроса, но присутствующая в опубликованном коде: нативное целое число и число раз никогда не нужно делать .new, поскольку они не являются объектами. типы. Это:

my uint32 $num = .new;

Должно быть просто:

my uint32 $num;

И

my num32 $float = .new: Num(1.0);

Должно быть просто:

my num32 $float = 1e0;

Использование показателя e делает литерал плавающим в Perl 6.

...