Raku 如何将指向 Buf 的指针传递给本地调用进行写入

标签 raku nativecall

我正在尝试包装 read函数来自 unistd.h ,但无法让它工作。
这是我所拥有的:(在文件中:read.raku)

use NativeCall;

# ssize_t read(int fd, void *buf, size_t count);
sub c_read(int32 $fd, Pointer $buf is rw, size_t $count --> ssize_t) is native is symbol('read') { * }

my $buf = Buf[byte].new(0 xx 5);
my $pbuf = nativecast(Pointer, $buf);
say c_read(3, $pbuf, 5);
say '---------------------';
say $buf;
我像这样从命令行(bash)测试它:
$ (exec 3< <(echo hello world); raku ./read.raku)
但我得到:
5
---------------------
Buf[byte]:0x<00 00 00 00 00>
所以看起来从 FD 3 读取的字节没有写入 Buf .
我也试过这个:
use NativeCall;

# ssize_t read(int fd, void *buf, size_t count);

sub c_read(int32 $fd, Pointer $buf is rw, size_t $count --> ssize_t) is native is symbol('read') { * }
sub c_malloc(size_t $size --> Pointer) is native is symbol('malloc') { * }

my $pbuf = nativecast(Pointer[byte], c_malloc(5));

say c_read(3, $pbuf, 5);
say '---------------------';
say $pbuf[^5];
但是我遇到了段错误,我猜是因为使用 $pbuf[^5] 取消引用到未经授权的内存位置.但即使只是 $pbuf.deref不提供读取的第一个字节。
所以我一定是做错了什么或者完全误解了如何使用 native 调用。
更新:
在玩了更多之后,看起来上面第二个片段的问题在于 is rw少量。这似乎有效:
use NativeCall;
use NativeHelpers::Blob;

sub c_read(int32 $fd, Pointer $buf, size_t $count --> ssize_t) is native is symbol('read') { * }

sub c_malloc(size_t $size --> Pointer) is native is symbol('malloc') { * }
my $pbuf := nativecast(Pointer[byte], c_malloc(5));

say c_read(3, $pbuf, 5);
say '---------------------';
say $pbuf[^5];   # (104 101 108 108 111)

最佳答案

好的,所以问题出在 rw赋予 Pointer $buf 的特征.我猜这会导致 read函数在写入时递增指针,因此在我以后使用它时会给出错误的地址。
这是两种情况的工作代码:

use NativeCall;

# ssize_t read(int fd, void *buf, size_t count);

sub c_read(int32 $fd, Pointer $buf, size_t $count --> ssize_t) is native is symbol('read') { * }


# Passing a pointer to a Buf directly:
{
    my $buf = Buf[byte].new(0 xx 5);
    my $pbuf = nativecast(Pointer[byte], $buf);
    say c_read(3, $pbuf, 5);
    say '---------------------';
    say $buf;

}


# Using malloc also works:
{
    sub c_malloc(size_t $size --> Pointer) is native is symbol('malloc') { * }
    my $pbuf = nativecast(Pointer[byte], c_malloc(5));

    say c_read(3, $pbuf, 5);
    say '---------------------';
    say $pbuf[^5];
}
像这样测试它:
$ (exec 3< <(echo hello world); perl6  ./read.raku)
5
---------------------
Buf[byte]:0x<68 65 6C 6C 6F>
5
---------------------
(32 119 111 114 108)

关于Raku 如何将指向 Buf 的指针传递给本地调用进行写入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63126852/

相关文章:

metaprogramming - 自省(introspection) : how do we get the name of a class within a class?

raku - Perl6哈希键已定义与存在

variables - 为什么 Perl 6 状态变量对于不同的文件表现不同?

arrays - 在 Perl 6 NativeCall CStruct 中声明一个数组

raku - Perl 6 NativeCall 和 C 源文件

raku - 如何为返回整个结构的 C 函数编写 Raku 声明?

utf-16 - Perl6 NativeCall with Str 被编码为 ('utf16' ) 得到随机损坏的结果

raku - 带有 ^ 的类方法名称没有被正确调用

raku - 如何在 Perl 6 中声明数字散列的散列?

raku - 在 Perl 6 NativeCall 中将指针传递给指针