如何在NativeCall接口中正确使用CPointer和CStruct

jjm*_*elo 8 posix perl6 nativecall

我试图得到这个NativeCall运行的例子:

use NativeCall;

class p_timespec is repr('CPointer') {
    has uint32 $.tv_sec;
    has long $.tv_nanosecs;
}

sub clock_gettime(uint32 $clock-id, p_timespec $tspec --> uint32) is native(Str) { * };

my p_timespec $this-time;

my $result = clock_gettime( 0, $this-time);

say "$result, $this-time";
Run Code Online (Sandbox Code Playgroud)

它只是段错误,这是你使用指针时发生的事情,你不应该.在这种情况下,这可能是由于声明p_timespec; 我实际上已将其声明为a CPointer,尽管结构应该没问题.但是,从分段错误来看,我无法理解究竟是什么问题.有人可以帮忙吗?

Jon*_*ton 9

这里有两件事是错的.

  1. CStruct应使用该表示
  2. 你需要创建一个结构实例来填充数据,否则你传递一个空指针

这似乎有效:

use NativeCall;

class p_timespec is repr('CStruct') {
    has uint32 $.tv_sec;
    has long $.tv_nanosecs;
}

sub clock_gettime(uint32 $clock-id, p_timespec $tspec --> uint32) is native(Str) { * };

my p_timespec $this-time .= new;

my $result = clock_gettime( 0, $this-time);

say "$result, $this-time.tv_sec(), $this-time.tv_nanosecs()";
Run Code Online (Sandbox Code Playgroud)

至于调试,Rakudo的安装过程也安装了a perl6-gdb-m和a perl6-valgrind-m; 后者虽然很慢,但往往会提供一些有关内存错误的有用信息.

  • 出于好奇,为什么几乎没有人使用`repr <CStruct>`语法? (2认同)
  • 一个`CStruct`实例已作为指向内存的指针传递,因此不需要额外的指针级别.当您想要将数据结构简单地作为不透明指针处理时,`CPointer`非常有用,而不需要关心它内部的内容.例如,当有一个C库来分配/释放结构并提供对其进行操作的函数时,这很好用,你永远不应该直接戳它. (2认同)