File Coverage

blib/lib/FFI/Library.pm
Criterion Covered Total %
statement 41 50 82.0
branch 20 34 58.8
condition 5 10 50.0
subroutine 10 10 100.0
pod 3 3 100.0
total 79 107 73.8


line stmt bran cond sub pod time code
1             package FFI::Library;
2              
3 3     3   167909 use strict;
  3         9  
  3         89  
4 3     3   14 use warnings;
  3         5  
  3         70  
5 3     3   14 use Carp ();
  3         14  
  3         164  
6 3     3   17 use constant _is_win => $^O =~ /^(MSWin32|cygwin|msys2?)$/;
  3         12  
  3         2063  
7              
8             # ABSTRACT: Perl Access to Dynamically Loaded Libraries
9             our $VERSION = '1.14'; # VERSION
10              
11             sub new
12             {
13 8     8 1 38773 my($class, $libname, $flags) = @_;
14 8 100       224 Carp::croak('Usage: $lib = FFI::Library->new($filename [, $flags ])')
15             unless @_ <= 3;
16              
17 7   50     48 $flags ||= 0;
18              
19 7 100 66     127 if(! defined $libname)
    100          
    50          
    100          
20             {
21 1         4 return bless {
22             impl => 'null',
23             }, $class;
24             }
25             elsif(ref $libname and int($libname) == int(\$0))
26             {
27 2         9 return $class->_dl_impl(undef, undef);
28             }
29             elsif(_is_win)
30             {
31 0         0 return $class->_dl_impl($libname, undef);
32             }
33             elsif(-e $libname)
34             {
35 3 50       52 return $class->_dl_impl(
36             $libname,
37             $flags == 0x01 ? FFI::Platypus::Lang::DL::RTLD_GLOBAL() : undef,
38             );
39             }
40             else
41             {
42 1         9 require DynaLoader;
43 1   33     319 my $so = DynaLoader::dl_findfile($libname) || $libname;
44 1   50     247 my $handle = DynaLoader::dl_load_file($so, $flags || 0);
45 1 50       10 return unless $handle;
46 0         0 return bless {
47             impl => 'dynaloader',
48             handle => $handle,
49             }, $class;
50             }
51             }
52              
53             sub _dl_impl
54             {
55 5     5   17 my($class, $path, $flags) = @_;
56 5         1010 require FFI::Platypus::DL;
57 5 50       7868 $flags = FFI::Platypus::DL::RTLD_PLATYPUS_DEFAULT()
58             unless defined $flags;
59 5         347 my $handle = FFI::Platypus::DL::dlopen($path, $flags);
60 5 50       26 return unless defined $handle;
61 5         60 bless { impl => 'dl', handle => $handle }, $class;
62             }
63              
64             sub address
65             {
66 11     11 1 1403 my($self, $name) = @_;
67              
68 11 50       42 if($self->{impl} eq 'dl')
    0          
    0          
69             {
70 11         90 return FFI::Platypus::DL::dlsym($self->{handle}, $name);
71             }
72             elsif($self->{impl} eq 'dynaloader')
73             {
74 0         0 return DynaLoader::dl_find_symbol($self->{handle}, $name);
75             }
76             elsif($self->{impl} eq 'null')
77             {
78 0         0 return;
79             }
80             else
81             {
82 0         0 Carp::croak("Unknown implementaton: @{[ $self->{impl} ]}");
  0         0  
83             }
84             }
85              
86             sub function
87             {
88 6     6 1 1877 my($self, $name, $sig) = @_;
89              
90 6         17 my $addr = $self->address($name);
91              
92 6 100       256 Carp::croak("Unknown function $name")
93             unless defined $addr;
94              
95 4         468 require FFI;
96 4     5   27 sub { FFI::call($addr, $sig, @_) };
  5         2316  
97             }
98              
99             sub DESTROY
100             {
101 6     6   34140 my($self) = @_;
102              
103 6 100       30 if($self->{impl} eq 'dl')
    50          
    50          
104             {
105 5         145 FFI::Platypus::DL::dlclose($self->{handle});
106             }
107             elsif($self->{impl} eq 'dynaloader')
108             {
109             DynaLoader::dl_free_file($self->{handle})
110 0 0         if defined &DynaLoader::dl_free_file;
111             }
112             elsif($self->{impl} eq 'null')
113             {
114             # do nothing
115             }
116             else
117             {
118 0           Carp::croak("Unknown implementaton: @{[ $self->{impl} ]}");
  0            
119             }
120             }
121              
122             1;
123              
124             __END__