Passing pointer to pointer in Perl 6 NativeCall

荒凉一梦 提交于 2019-12-23 10:14:21

问题


I'm trying to use NativeCall to interact with some C functions.

For one case, I need to pass in pointers that get updated by the function, so it wants a pointer to a pointer, 'void **'.

I tried it like this:

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);
    }
}

It doesn't work. The pointers don't get updated by the function.

Since a C array is basically a pointer to a pointer, I can fake it like this:

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];
    }
}

It works fine like this. It just seems like the "is rw" should force the pointer to pointer and it should work the first way.

What am I doing wrong?


回答1:


Last I checked, NativeCall still had some rough edges that at times necessitate a bit of creativity; this might be one of those cases.

One workaround I know of is to just use pointer-sized integers (specifically, size_t or ssize_t) as parameter and attribute types on the Perl6 side1, which should work as expected with is rw.

It's easy to convert between integers and pointers: use prefix +, .Int or even just assignment to an integer-typed variable to convert to integer, and Pointer.new(…) or nqp::box_i(…, Pointer) for the other direction.

If so desired, accessor methods can be used to automate this conversion.


1 if you do go this way, a definition such as constant intptr = ssize_t will help readability




回答2:


This works for me in the version 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;


来源:https://stackoverflow.com/questions/43543217/passing-pointer-to-pointer-in-perl-6-nativecall

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!