Passing pointer to pointer in Perl 6 NativeCall

I am trying to use NativeCall to interact with some C functionality.

In one case, I need to pass pointers that are updated, so it wants a pointer to a "void **" pointer.

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

      

This does not work. Pointers are not updated by the function.

Since the C array is basically a pointer to a pointer, I can fake it for example:

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

      

This works great. It seems like "rw" should force a pointer to a pointer, and it should work the first way.

What am I doing wrong?

+3


source to share


2 answers


Last I checked, NativeCall

it still had some rough edges that require a little creativity at times; it could be one of these cases.

A workaround I know is to use pointer-sized integers (specifically, size_t

or ssize_t

) as parameters and attribute types on the Perl6 side 1 which should work as expected with is rw

.

Easy to convert integers and pointers: use a prefix +

, .Int

or even just assign an integer variable to convert to integer and Pointer.new(…)

or nqp::box_i(…, Pointer)

in the other direction.



Accessor methods can be used to automate this transformation if desired.


1 if you do, a definition such as constant intptr = ssize_t

will help readability

+3


source


This works for me in 2017.09 version:



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;

      

+1


source







All Articles