5

我正在尝试使用 NativeCall 与一些 C 函数进行交互。

对于一种情况,我需要传入由函数更新的指针,因此它需要一个指向指针“void **”的指针。

我试过这样:

class Foo
{
    has Pointer $.first;
    has Pointer $.last;

    sub somefunc(Pointer is rw, Pointer is rw, Str) is native { * }

    method myfunc(Str $arg) {
        somefunc($!first, $!last, $arg);
    }
}

它不起作用。指针不会被函数更新。

由于 C 数组基本上是指向指针的指针,因此我可以像这样伪造它:

class Foo
{
    has Pointer $.first;
    has Pointer $.last;

    sub somefunc(CArray[Pointer], CArray[Pointer], Str) is native { * }

    method myfunc(Str $arg) {
        my $first = CArray[Pointer].new($!first);
        my $last = CArray[Pointer].new($!last);
        somefunc($first, $last, $arg);
        $!first = $first[0];
        $!last = $last[0];
    }
}

它像这样工作得很好。看起来“is rw”应该强制指针指向指针,它应该以第一种方式工作。

我究竟做错了什么?

4

2 回答 2

4

最后我检查了一下,NativeCall仍然有一些粗糙的边缘,有时需要一点创造力;这可能是其中一种情况。

我知道的一种解决方法是仅使用指针大小的整数(特别是size_tor ssize_t)作为 Perl6 侧1上的参数和属性类型,这应该与is rw.

整数和指针之间的转换很容易:使用 prefix +.Int甚至只是赋值给一个整数类型的变量以转换为整数,Pointer.new(…)或者nqp::box_i(…, Pointer)用于另一个方向。

如果需要,可以使用访问器方法来自动执行此转换。


1如果你这样做了,这样的定义constant intptr = ssize_t将有助于提高可读性

于 2017-04-22T00:07:11.957 回答
2

这在 2017.09 版本中适用于我:

class Pdu is repr('CStruct') { ... }

sub snmp_synch_response(Snmp-session, Pdu, Pointer[Pdu] is rw) returns int32 is native("netsnmp") { * };

my $p = Pointer[Pdu].new;
my $status = snmp_synch_response($ss, $pdu, $p);
say $status, "-", $p;

my $resp = $p.deref;
say $resp;
于 2017-09-26T09:26:23.947 回答