5

将数据放入 Perl 6 Native 指针中没什么大不了的:

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显然是在相反的方向上工作,或者至少不是在强制转换为非本地类型的方向上(这应该是显而易见的姓名)。你会怎么做?

更新:例如,使用 Array 会使它更可行。然而

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

这有效,但会产生错误:Don't know how many elements a C array returned from a library

更新 2:根据Christoph 的回答(谢谢!),我们可以对此进行详细说明,我们可以将这些值放回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知道何时结束循环,这仍然有点 hacky。有没有更直接的方法?或者只是一种使用 Bufs/Blobs 的方式,以便可以轻松地将它们复制到 Native 领域并返回?

4

2 回答 2

7

完整示例:

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方法,但您的代码还有其他一些问题:

  • 在声明中使用 ofint32而不是size_tmemcpy
  • 的参数顺序错误memcpy,这意味着您将从未初始化的内存中读取的两个字节复制到您所谓的不可变 Blob
  • 在您可能应该使用大小整数类型的地方使用plain int,例如int16

Pointer还要注意在声明中使用 plain memcpy,这将允许您传入任何指针类型而无需不断地进行强制转换。

于 2018-06-28T12:42:25.313 回答
2

使用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;

该程序扩展了 Christoph 的答案,添加了blob-from-pointer将返回原始 blob: 的函数Blob[int8]:0x<22 33>。这个答案现在也在文档中

于 2018-06-28T16:53:11.397 回答