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?
source to share
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
source to share
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;
source to share