从Native指针中获取数据

jjm*_*elo 4 perl6 nativecall

将数据导入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>
Run Code Online (Sandbox Code Playgroud)

但是,我认为没有办法让它们脱离Pointer[int]另一个而不是创建一个函数来完成它,因为它nativecast显然是在相反的方向上工作,或者至少不是在向非本地类型转换的方向(这应该是显而易见的名称).你会怎么做?

更新:例如,使用数组会使其更加可行.然而

my $inter = nativecast(CArray[int16], $dest);
.say for $inter.list;
Run Code Online (Sandbox Code Playgroud)

这有效,但会产生错误: 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;
Run Code Online (Sandbox Code Playgroud)

我们需要将指针强制转换为缓冲区使用的完全相同的类型,然后我们使用指针算法来运行它.但是,我们$blob.bytes用来知道何时结束循环,它仍然是一种hacky.会有更直接的方式吗?或者只是一种使用Bufs/Blob的方式,以便它们可以轻松地复制到Native领域并返回?

Chr*_*oph 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');
Run Code Online (Sandbox Code Playgroud)

我假设您正在寻找该deref方法,但您的代码还存在一些其他问题:

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

另请注意Pointer在声明中使用plain memcpy,这将允许您传入任何指针类型而无需不断演员.

  • @jjmerelo:相反的顺序是由于[little endian](https://en.wikipedia.org/wiki/Endianness#Little-endian)整数编码; 在你的第二个评论中,我选择了`nativesizeof(int16)`因为在可能的情况下提供目标参数的大小可以说是"更安全"; 请注意,我假设您的目标是创建一个16位整数,而不是任意本机blob (2认同)

jjm*_*elo 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;
Run Code Online (Sandbox Code Playgroud)

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