How to pass user data to a callback function
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 );
I realize this is an old question and you've probably implemented workarounds long ago, but in the interest of catching others with a similar issue, I'll post my answer now.
I've had to do this several times for different NativeCall
library interfaces, so I decided to package it up into a NativeHelpers::Callback module.
It provides some simple methods to associate a perl object with an CPointer
and easily look it up from within a callback function.
This is all untested, but something like this should work for your case:
use NativeHelpers::Callback :cb;
class ExifEntry is repr('CPointer') { ... }
sub exif_content_foreach_entry(ExifContent $exifcontent,
&func (ExifEntry $entry, int64), int64) is native(LIB) is export { * }
class MyPerlObject {
has $.entry;
has Buf $.buf;
...
}
sub MyCallBack(ExifEntry $entry, int64 $id) {
my MyPerlObject $object = cb.lookup($id);
... do stuff with $object ...
}
my ExifEntry $entry = ...;
my MyPerlObject $object = MyPerlObject.new(:$entry, buf => ...);
cb.store($object, $entry);
exif_content_foreach_entry($exifcontent, &MyCallBack, cb.id($entry));