I'm working on a NativeCall interface; there's a C function which accepts a callback, defined as:
typedef void (* ExifContentForeachEntryFunc) (ExifEntry *, void *user_data);
void exif_content_foreach_entry (ExifContent *content, ExifContentForeachEntryFunc func, void *user_data);
My first take has been:
sub exif_content_foreach_entry(ExifContent $exifcontent, &func (ExifEntry $entry, Buf $data), Buf $user_data) is native(LIB) is export { * }
but when invoked this function generates an error:
Internal error: unhandled dyncall callback argument type
in method CALL-ME at /opt/rakudo-pkg/share/perl6/sources/24DD121B5B4774C04A7084827BFAD92199756E03 (NativeCall) line 588
If I ignore the user_data argument, everything works, so the rest of the declaration is fine: I just don't get to pass any additional data to the callback function.
On other occasions I used a Buf to pass a block of (possibly) binary data to a C function and it worked; the difference here is the callback function. Any idea how to solve this problem?
(using perl6 2018.03)
I am not sure how to pass a Buf
as user data since Buf
is not a native type. But you could use for instance a CStruct
instead:
class UserData is repr('CStruct') {
has int32 $.dummy;
}
Then the declaration would be:
sub exif_content_foreach_entry(
ExifContent $exifcontent,
&func (ExifEntry $entry, UserData $data),
UserData $user_data) is native(LIB) is export { * }
And the callback can be declared and defined as for example:
sub my-callback (ExifEntry $entry, UserData $data) {
say "In callback";
say "Value of data: ", $data.dummy;
}
Edit:
Here is a workaround to pass a Perl 6 type like Buf
(i.e not a native type) to the callback using a closure. For example:
my $buf = Buf.new( 1, 2, 3);
my $callback = my sub (ExifEntry $entry, UserData $data) {
my-callback( $entry, $buf);
}
Then declare the real callback my-callback
like this:
sub my-callback (ExifEntry $entry, Buf $data) {
say "In callback";
say "Value of data: ", $data;
}
And call the library function like this:
exif_content_foreach_entry( $content, &$callback, $data );