FFI-Platypus
view release on metacpan or search on metacpan
lib/FFI/Platypus.pm view on Meta::CPAN
0
6
=head3 Discussion
Starting with the Platypus version 2 API, you can also pass an array reference
in to a pointer argument.
In C pointer and array arguments are often used somewhat interchangeably. In
this example we have an C<array_sum> function that takes a zero terminated
array of integers and computes the sum. If the pointer to the array is zero
(C<0>) then we return C<-1> to indicate an error.
This is the main advantage from Perl for using pointer argument rather than
an array one: the array argument will not let you pass in C<undef> / C<NULL>.
=head2 Sending Strings to GUI on Unix with libnotify
=head3 C API
L<Libnotify Reference Manual|https://developer-old.gnome.org/libnotify/unstable>
=head3 Perl Source
use FFI::CheckLib;
use FFI::Platypus 2.00;
my $ffi = FFI::Platypus->new(
api => 2,
lib => find_lib_or_die(lib => 'notify'),
);
$ffi->attach( notify_init => ['string'] );
$ffi->attach( notify_uninit => [] );
$ffi->attach( notify_notification_new => ['string', 'string', 'string'] => 'opaque' );
$ffi->attach( notify_notification_show => ['opaque', 'opaque'] );
my $message = join "\n",
"Hello from Platypus!",
"Welcome to the fun",
"world of FFI";
notify_init('Platypus Hello');
my $n = notify_notification_new('Platypus Hello World', $message, 'dialog-information');
notify_notification_show($n, undef);
notify_uninit();
=head3 Execute
$ perl notify.pl
=for html <p>And this is what it will look like:</p>
<div style="display: flex">
<div style="margin: 3px; flex: 1 1 50%">
<img alt="Test" src="/examples//notify.png">
</div>
</div>
=head3 Discussion
The GNOME project provides an API to send notifications to its desktop environment.
Nothing here is particularly new: all of the types and techniques are ones that we
have seen before, except we are using a third party library, instead of using our
own C code or the standard C library functions.
When using a third party library you have to know the name or location of it, which
is not typically portable, so here we use L<FFI::CheckLib>'s
L<find_lib_or_die function|FFI::CheckLib/find_lib_or_die>. If the library is not
found the script will die with a useful diagnostic. L<FFI::CheckLib> has a number
of useful features and will integrate nicely with L<Alien::Build> based L<Alien>s.
=head2 The Win32 API with MessageBoxW
=head3 Win32 API
L<MessageBoxW function (winuser.h)|https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messageboxw>
=head3 Perl Source
use utf8;
use FFI::Platypus 2.00;
my $ffi = FFI::Platypus->new(
api => 2,
lib => [undef],
);
# see FFI::Platypus::Lang::Win32
$ffi->lang('Win32');
# Send a Unicode string to the Windows API MessageBoxW function.
use constant MB_OK => 0x00000000;
use constant MB_DEFAULT_DESKTOP_ONLY => 0x00020000;
$ffi->attach( [MessageBoxW => 'MessageBox'] => [ 'HWND', 'LPCWSTR', 'LPCWSTR', 'UINT'] => 'int' );
MessageBox(undef, "I â¤ï¸ Platypus", "Confession", MB_OK|MB_DEFAULT_DESKTOP_ONLY);
=head3 Execute
$ perl win32_messagebox.pl
=for html <p>And this is what it will look like:</p>
<div style="display: flex">
<div style="margin: 3px; flex: 1 1 50%">
<img alt="Test" src="/examples/win32_messagebox.png">
</div>
</div>
=head3 Discussion
The API used by Microsoft Windows presents some unique
challenges. On 32 bit systems a different ABI is used than what
is used by the standard C library. It also provides a rats nest of
type aliases. Finally if you want to talk Unicode to any of the
Windows API you will need to use C<UTF-16LE> instead of C<UTF-8>
which is native to Perl. (The Win32 API refers to these as
C<LPWSTR> and C<LPCWSTR> types). As much as possible the Win32
"language" plugin attempts to handle these challenges transparently.
For more details see L<FFI::Platypus::Lang::Win32>.
=head3 Discussion
The libnotify library is a desktop GUI notification system for the
GNOME Desktop environment. This script sends a notification event that
should show up as a balloon, for me it did so in the upper right hand
corner of my screen.
=head2 Structured Data Records (by pointer or by reference)
=head3 C API
L<cppreference - localtime|https://en.cppreference.com/w/c/chrono/localtime>
=head3 Perl Source
use FFI::Platypus 2.00;
use FFI::C;
my $ffi = FFI::Platypus->new(
api => 2,
lib => [undef],
);
FFI::C->ffi($ffi);
package Unix::TimeStruct {
FFI::C->struct(tm => [
tm_sec => 'int',
tm_min => 'int',
tm_hour => 'int',
tm_mday => 'int',
tm_mon => 'int',
tm_year => 'int',
tm_wday => 'int',
tm_yday => 'int',
tm_isdst => 'int',
tm_gmtoff => 'long',
_tm_zone => 'opaque',
]);
# For now 'string' is unsupported by FFI::C, but we
# can cast the time zone from an opaque pointer to
# string.
sub tm_zone {
my $self = shift;
$ffi->cast('opaque', 'string', $self->_tm_zone);
}
# attach the C localtime function
$ffi->attach( localtime => ['time_t*'] => 'tm', sub {
my($inner, $class, $time) = @_;
$time = time unless defined $time;
$inner->(\$time);
});
}
# now we can actually use our Unix::TimeStruct class
my $time = Unix::TimeStruct->localtime;
printf "time is %d:%d:%d %s\n",
$time->tm_hour,
$time->tm_min,
$time->tm_sec,
$time->tm_zone;
( run in 1.911 second using v1.01-cache-2.11-cpan-14f38c9f855 )