File Coverage

blib/lib/FFI.pm
Criterion Covered Total %
statement 31 32 96.8
branch 2 4 50.0
condition 1 3 33.3
subroutine 9 9 100.0
pod 2 2 100.0
total 45 50 90.0


line stmt bran cond sub pod time code
1             package FFI;
2              
3 4     4   162542 use strict;
  4         18  
  4         118  
4 4     4   20 use warnings;
  4         8  
  4         91  
5 4     4   20 use Carp ();
  4         5  
  4         57  
6 4     4   2169 use FFI::Platypus;
  4         21912  
  4         360  
7 4   33 4   32 use constant _is_win32 => $^O =~ /^(MSWin32|cygwin|msys2?)$/ && FFI::Platypus->abis->{stdcall};
  4         7  
  4         2201  
8              
9             # ABSTRACT: Perl Foreign Function Interface based on libffi
10             our $VERSION = '0.07'; # VERSION
11              
12             our $ffi = FFI::Platypus->new;
13             $ffi->lib(undef);
14              
15             my $stdcall_ffi = _is_win32
16             ? do {
17             my $ffi = FFI::Platypus->new;
18             $ffi->lib(undef);
19             $ffi->abi('stdcall');
20             }
21             : $ffi;
22              
23             our %typemap = qw(
24             c char
25             C uchar
26             s short
27             S ushort
28             i int
29             I uint
30             l long
31             L ulong
32             f float
33             d double
34             p string
35             v void
36             o opaque
37             );
38              
39             sub _ffi
40             {
41 8 50   8   56 if($_[0] =~ s/^([sc])//)
42             {
43 8 50       35 return $stdcall_ffi if $1 eq 's';
44             }
45             else
46             {
47 0         0 Carp::croak("first character of signature must be s or c");
48             }
49            
50 8         18 $ffi;
51             }
52              
53             sub call
54             {
55 7     7 1 28046 my($addr, $signature, @args) = @_;
56 7         21 my $ffi = _ffi($signature);
57 7         23 my($ret_type, @args_types) = map { $typemap{$_} } split //, $signature;
  17         54  
58 7         33 $ffi->function($addr => \@args_types => $ret_type)->call(@args);
59             }
60              
61             sub callback
62             {
63 1     1 1 10 my($signature, $sub) = @_;
64 1         5 my $ffi = _ffi($signature);
65 1         5 my($ret_type, @args_types) = map { $typemap{$_} } split //, $signature;
  3         9  
66 1         6 my $type = '(' . join(',', @args_types) . ')->' . $ret_type;
67 1         6 my $closure = $ffi->closure($sub);
68 1         1158 bless {
69             addr => $ffi->cast($type => 'opaque', $closure),
70             sub => $sub,
71             closure => $closure,
72             }, 'FFI::Callback';
73             }
74              
75             package FFI::Callback;
76              
77 1     1   12 sub addr { shift->{addr} }
78              
79             1;
80              
81             __END__