Получение данных из родных указателей - PullRequest
0 голосов
/ 28 июня 2018

Нетрудно получить данные в родных указателях Perl 6:

sub memcpy( Pointer[void] $source, Pointer[void] $destination, int32 $size ) is native { * };
my Blob $blob = Blob.new(0x22, 0x33);
my Pointer[void] $src-memcpy = nativecast(Pointer[void], $blob);
my Pointer[void] $dest-memcpy = malloc( 32 );
memcpy($src-memcpy,$dest-memcpy,2);
my Pointer[int] $inter = nativecast(Pointer[int], $dest-memcpy);
say $inter; # prints NativeCall::Types::Pointer[int]<0x4499560>

Однако я не вижу способа вытащить их из Pointer[int], кроме создания функции для этого, поскольку nativecast, очевидно, работает в противоположном направлении или, по крайней мере, не в направление приведения к неродным типам (что должно быть очевидно по его названию). Как бы вы это сделали?

Обновление : Например, использование массива сделает его более работоспособным. Тем не менее

my $inter = nativecast(CArray[int16], $dest);
.say for $inter.list;

Это работает, но выдает ошибку: Don't know how many elements a C array returned from a library

Обновление 2 : Следуя ответу Кристофа (спасибо!), Мы можем еще немного проработать это, и мы можем вернуть значения обратно в Buf

sub malloc(size_t $size --> Pointer) is native {*}
sub memcpy(Pointer $dest, Pointer $src, size_t $size --> Pointer) is native {*}

my $blob = Blob.new(0x22, 0x33);
my $src = nativecast(Pointer, $blob);
my $dest = malloc( $blob.bytes );
memcpy($dest, $src, $blob.bytes);
my $inter = nativecast(Pointer[int8], $dest);

my $cursor = $inter;

my Buf $new-blob .= new() ;
for 1..$blob.bytes {
    $new-blob.append: $cursor.deref;
    $cursor++;
}

say $new-blob;

Нам нужно привести указатель к тому же типу, который используется буфером, а затем мы используем арифметику указателя , чтобы запустить его. Тем не менее, мы используем $blob.bytes, чтобы знать, когда заканчивать цикл, и он все еще довольно хакерский. Был бы более прямой путь? Или просто способ работы с Bufs / Blob, чтобы их можно было легко скопировать в область Native и обратно?

Ответы [ 2 ]

0 голосов
/ 28 июня 2018

Использование NativeHelpers::Blob:

use NativeCall;
use NativeHelpers::Blob;

sub malloc(size_t $size --> Pointer) is native {*}
sub memcpy(Pointer $dest, Pointer $src, size_t $size --> Pointer) is native {*}

my $blob = Blob.new(0x22, 0x33);
my $src = nativecast(Pointer, $blob);
my $dest = malloc( $blob.bytes );
memcpy($dest, $src, $blob.bytes);
my $inter = nativecast(Pointer[int8], $dest);

my Blob $esponja = blob-from-pointer( $inter, :2elems, :type(Blob[int8]));
say $esponja;

Эта программа расширяет ответ Кристофа , добавляя функцию blob-from-pointer, которая будет возвращать исходный BLOB-объект: Blob[int8]:0x<22 33>. Этот ответ также теперь в документации

0 голосов
/ 28 июня 2018

Полный пример:

use NativeCall;

sub malloc(size_t $size --> Pointer) is native {*}
sub memcpy(Pointer $dest, Pointer $src, size_t $size --> Pointer) is native {*}

my $blob = Blob.new(0x22, 0x33);
my $src = nativecast(Pointer, $blob);
my $dest = malloc(nativesizeof(int16));
memcpy($dest, $src, nativesizeof(int16));
my $inter = nativecast(Pointer[int16], $dest);
say $inter.deref.fmt('%x');

Я предполагаю, что вы искали метод deref, но с вашим кодом было несколько других проблем:

  • использование int32 вместо size_t в объявлении memcpy
  • неправильный порядок аргументов memcpy, что означает, что вы копировали два байта, считанные из неинициализированной памяти, в ваш предположительно неизменный BLOB-объект
  • использование простого int, где вы, вероятно, должны были использовать целочисленный тип размера, такой как int16

Также обратите внимание на использование обычного Pointer в объявлении memcpy, которое позволит вам передавать любой тип указателя без необходимости постоянного приведения.

...