New upstream version 1.33
gregor herrmann
3 years ago
0 | 0 | Revision history for FFI-Platypus |
1 | ||
2 | 1.33 2020-09-28 10:47:26 -0600 | |
3 | - FFI::Platypus::Declare is no longer part of this distribution. It is | |
4 | no available from FFI-Platypus-Declare instead. It has already | |
5 | been discouraged for quite some time. (gh#285) | |
6 | - Fix bug where bundled .so name could incorrectly get double colons (::) | |
7 | in the name in development mode only. This is probably only a problem | |
8 | on Windows. (gh#284) | |
1 | 9 | |
2 | 10 | 1.32 2020-09-21 04:25:13 -0600 |
3 | 11 | - Fix unsupported Perl tests. |
152 | 152 | lib/FFI/Platypus/Closure.pm |
153 | 153 | lib/FFI/Platypus/Constant.pm |
154 | 154 | lib/FFI/Platypus/DL.pm |
155 | lib/FFI/Platypus/Declare.pm | |
156 | 155 | lib/FFI/Platypus/Function.pm |
157 | 156 | lib/FFI/Platypus/Internal.pm |
158 | 157 | lib/FFI/Platypus/Lang.pm |
234 | 233 | t/ffi_platypus_bundle.t |
235 | 234 | t/ffi_platypus_closure.t |
236 | 235 | t/ffi_platypus_constant.t |
237 | t/ffi_platypus_declare.t | |
238 | 236 | t/ffi_platypus_dl.t |
239 | 237 | t/ffi_platypus_function.t |
240 | 238 | t/ffi_platypus_function_wrapper.t |
86 | 86 | }, |
87 | 87 | "x_IRC" : "irc://irc.perl.org/#native" |
88 | 88 | }, |
89 | "version" : "1.32", | |
89 | "version" : "1.33", | |
90 | 90 | "x_contributors" : [ |
91 | 91 | "Graham Ollis <plicease@cpan.org>", |
92 | 92 | "Bakkiaraj Murugesan (bakkiaraj)", |
105 | 105 | "Meredith (merrilymeredith, MHOWARD)", |
106 | 106 | "Diab Jerius (DJERIUS)" |
107 | 107 | ], |
108 | "x_generated_by_perl" : "v5.32.0", | |
108 | "x_generated_by_perl" : "v5.33.0", | |
109 | 109 | "x_serialization_backend" : "Cpanel::JSON::XS version 4.19", |
110 | 110 | "x_spdx_expression" : "Artistic-1.0-Perl OR GPL-1.0-or-later", |
111 | 111 | "x_use_unsafe_inc" : 0 |
36 | 36 | bugtracker: https://github.com/PerlFFI/FFI-Platypus/issues |
37 | 37 | homepage: https://metacpan.org/pod/FFI::Platypus |
38 | 38 | repository: git://github.com/PerlFFI/FFI-Platypus.git |
39 | version: '1.32' | |
39 | version: '1.33' | |
40 | 40 | x_contributors: |
41 | 41 | - 'Graham Ollis <plicease@cpan.org>' |
42 | 42 | - 'Bakkiaraj Murugesan (bakkiaraj)' |
54 | 54 | - 'Håkon Hægland (hakonhagland, HAKONH)' |
55 | 55 | - 'Meredith (merrilymeredith, MHOWARD)' |
56 | 56 | - 'Diab Jerius (DJERIUS)' |
57 | x_generated_by_perl: v5.32.0 | |
57 | x_generated_by_perl: v5.33.0 | |
58 | 58 | x_serialization_backend: 'YAML::Tiny version 1.73' |
59 | 59 | x_spdx_expression: 'Artistic-1.0-Perl OR GPL-1.0-or-later' |
60 | 60 | x_use_unsafe_inc: 0 |
4 | 4 | exit; |
5 | 5 | } |
6 | 6 | } |
7 | # This file was automatically generated by Dist::Zilla::Plugin::Author::Plicease::MakeMaker v2.56. | |
7 | # This file was automatically generated by Dist::Zilla::Plugin::Author::Plicease::MakeMaker v2.57. | |
8 | 8 | use strict; |
9 | 9 | use warnings; |
10 | 10 | use 5.008004; |
43 | 43 | "lib/FFI/Platypus/Closure.pm" => "\$(INST_LIB)/FFI/Platypus/Closure.pm", |
44 | 44 | "lib/FFI/Platypus/Constant.pm" => "\$(INST_LIB)/FFI/Platypus/Constant.pm", |
45 | 45 | "lib/FFI/Platypus/DL.pm" => "\$(INST_LIB)/FFI/Platypus/DL.pm", |
46 | "lib/FFI/Platypus/Declare.pm" => "\$(INST_LIB)/FFI/Platypus/Declare.pm", | |
47 | 46 | "lib/FFI/Platypus/Function.pm" => "\$(INST_LIB)/FFI/Platypus/Function.pm", |
48 | 47 | "lib/FFI/Platypus/Internal.pm" => "\$(INST_LIB)/FFI/Platypus/Internal.pm", |
49 | 48 | "lib/FFI/Platypus/Lang.pm" => "\$(INST_LIB)/FFI/Platypus/Lang.pm", |
82 | 81 | "Capture::Tiny" => 0, |
83 | 82 | "Test::More" => "0.98" |
84 | 83 | }, |
85 | "VERSION" => "1.32", | |
84 | "VERSION" => "1.33", | |
86 | 85 | "test" => { |
87 | 86 | "TESTS" => "t/*.t" |
88 | 87 | } |
4 | 4 | |
5 | 5 | VERSION |
6 | 6 | |
7 | version 1.32 | |
7 | version 1.33 | |
8 | 8 | |
9 | 9 | SYNOPSIS |
10 | 10 | |
1433 | 1433 | For more details on enumerated types see "Enum types" in |
1434 | 1434 | FFI::Platypus::Type. |
1435 | 1435 | |
1436 | There is also a type plugin (FFI::Platypus::Type::Enum) that can be | |
1437 | helpful in writing interfaces that use enums. | |
1438 | ||
1436 | 1439 | Memory leaks |
1437 | 1440 | |
1438 | 1441 | There are a couple places where memory is allocated, but never |
2 | 2 | license = Perl_5 |
3 | 3 | copyright_holder = Graham Ollis |
4 | 4 | copyright_year = 2015,2016,2017,2018,2019,2020 |
5 | version = 1.32 | |
5 | version = 1.33 | |
6 | 6 | |
7 | 7 | ; authordep ExtUtils::MakeMaker |
8 | 8 |
5 | 5 | |
6 | 6 | include/ppport.h -- Perl/Pollution/Portability Version 3.57 |
7 | 7 | |
8 | Automatically created by Devel::PPPort running under perl 5.032000. | |
8 | Automatically created by Devel::PPPort running under perl 5.033000. | |
9 | 9 | |
10 | 10 | Do NOT edit this file directly! -- Edit PPPort_pm.PL and the |
11 | 11 | includes in parts/inc/ instead. |
9 | 9 | use overload '""' => sub { $_[0]->path }, bool => sub { 1 }, fallback => 1; |
10 | 10 | |
11 | 11 | # ABSTRACT: Base class for File::Build files |
12 | our $VERSION = '1.32'; # VERSION | |
12 | our $VERSION = '1.33'; # VERSION | |
13 | 13 | |
14 | 14 | |
15 | 15 | sub new |
157 | 157 | |
158 | 158 | =head1 VERSION |
159 | 159 | |
160 | version 1.32 | |
160 | version 1.33 | |
161 | 161 | |
162 | 162 | =head1 SYNOPSIS |
163 | 163 |
10 | 10 | use FFI::Build::File::Object; |
11 | 11 | |
12 | 12 | # ABSTRACT: Class to track C source file in FFI::Build |
13 | our $VERSION = '1.32'; # VERSION | |
13 | our $VERSION = '1.33'; # VERSION | |
14 | 14 | |
15 | 15 | |
16 | 16 | sub accept_suffix |
185 | 185 | |
186 | 186 | =head1 VERSION |
187 | 187 | |
188 | version 1.32 | |
188 | version 1.33 | |
189 | 189 | |
190 | 190 | =head1 SYNOPSIS |
191 | 191 |
7 | 7 | use constant default_encoding => ':utf8'; |
8 | 8 | |
9 | 9 | # ABSTRACT: Class to track C source file in FFI::Build |
10 | our $VERSION = '1.32'; # VERSION | |
10 | our $VERSION = '1.33'; # VERSION | |
11 | 11 | |
12 | 12 | |
13 | 13 | sub accept_suffix |
41 | 41 | |
42 | 42 | =head1 VERSION |
43 | 43 | |
44 | version 1.32 | |
44 | version 1.33 | |
45 | 45 | |
46 | 46 | =head1 SYNOPSIS |
47 | 47 |
6 | 6 | use constant default_encoding => ':raw'; |
7 | 7 | |
8 | 8 | # ABSTRACT: Class to track object file in FFI::Build |
9 | our $VERSION = '1.32'; # VERSION | |
9 | our $VERSION = '1.33'; # VERSION | |
10 | 10 | |
11 | 11 | |
12 | 12 | sub default_suffix |
28 | 28 | |
29 | 29 | =head1 VERSION |
30 | 30 | |
31 | version 1.32 | |
31 | version 1.33 | |
32 | 32 | |
33 | 33 | =head1 SYNOPSIS |
34 | 34 |
7 | 7 | use Carp (); |
8 | 8 | |
9 | 9 | # ABSTRACT: Class to track object file in FFI::Build |
10 | our $VERSION = '1.32'; # VERSION | |
10 | our $VERSION = '1.33'; # VERSION | |
11 | 11 | |
12 | 12 | |
13 | 13 | sub default_suffix |
39 | 39 | |
40 | 40 | =head1 VERSION |
41 | 41 | |
42 | version 1.32 | |
42 | version 1.33 | |
43 | 43 | |
44 | 44 | =head1 SYNOPSIS |
45 | 45 |
12 | 12 | use ExtUtils::MakeMaker 7.12; |
13 | 13 | |
14 | 14 | # ABSTRACT: FFI::Build installer code for ExtUtils::MakeMaker |
15 | our $VERSION = '1.32'; # VERSION | |
15 | our $VERSION = '1.33'; # VERSION | |
16 | 16 | |
17 | 17 | |
18 | 18 | sub new |
307 | 307 | |
308 | 308 | =head1 VERSION |
309 | 309 | |
310 | version 1.32 | |
310 | version 1.33 | |
311 | 311 | |
312 | 312 | =head1 SYNOPSIS |
313 | 313 |
10 | 10 | use FFI::Platypus::ShareConfig; |
11 | 11 | |
12 | 12 | # ABSTRACT: Platform specific configuration. |
13 | our $VERSION = '1.32'; # VERSION | |
13 | our $VERSION = '1.33'; # VERSION | |
14 | 14 | |
15 | 15 | |
16 | 16 | sub new |
420 | 420 | |
421 | 421 | =head1 VERSION |
422 | 422 | |
423 | version 1.32 | |
423 | version 1.33 | |
424 | 424 | |
425 | 425 | =head1 SYNOPSIS |
426 | 426 |
11 | 11 | use File::Path (); |
12 | 12 | |
13 | 13 | # ABSTRACT: Build shared libraries for use with FFI |
14 | our $VERSION = '1.32'; # VERSION | |
14 | our $VERSION = '1.33'; # VERSION | |
15 | 15 | |
16 | 16 | |
17 | 17 | sub _native_name |
301 | 301 | |
302 | 302 | =head1 VERSION |
303 | 303 | |
304 | version 1.32 | |
304 | version 1.33 | |
305 | 305 | |
306 | 306 | =head1 SYNOPSIS |
307 | 307 |
8 | 8 | our @EXPORT = grep /^arguments_/, keys %FFI::Platypus::API::; |
9 | 9 | |
10 | 10 | # ABSTRACT: Platypus arguments and return value API for custom types |
11 | our $VERSION = '1.32'; # VERSION | |
11 | our $VERSION = '1.33'; # VERSION | |
12 | 12 | |
13 | 13 | |
14 | 14 | 1; |
25 | 25 | |
26 | 26 | =head1 VERSION |
27 | 27 | |
28 | version 1.32 | |
28 | version 1.33 | |
29 | 29 | |
30 | 30 | =head1 SYNOPSIS |
31 | 31 |
9 | 9 | our @EXPORT_OK = qw ( scalar_to_pointer grow set_used_length window ); |
10 | 10 | |
11 | 11 | # ABSTRACT: Convert scalars to C buffers |
12 | our $VERSION = '1.32'; # VERSION | |
12 | our $VERSION = '1.33'; # VERSION | |
13 | 13 | |
14 | 14 | |
15 | 15 | use constant _incantation => |
49 | 49 | |
50 | 50 | =head1 VERSION |
51 | 51 | |
52 | version 1.32 | |
52 | version 1.33 | |
53 | 53 | |
54 | 54 | =head1 SYNOPSIS |
55 | 55 |
5 | 5 | use Carp (); |
6 | 6 | |
7 | 7 | # ABSTRACT: Bundle foreign code with your Perl module |
8 | our $VERSION = '1.32'; # VERSION | |
8 | our $VERSION = '1.33'; # VERSION | |
9 | 9 | |
10 | 10 | |
11 | 11 | package FFI::Platypus; |
79 | 79 | my($output, $error) = Capture::Tiny::capture_merged(sub { |
80 | 80 | $lib = eval { |
81 | 81 | my $dist_name = $package; |
82 | $dist_name =~ s/::/-/; | |
82 | $dist_name =~ s/::/-/g; | |
83 | 83 | my $fbmm = FFI::Build::MM->new( save => 0 ); |
84 | 84 | $fbmm->mm_args( DISTNAME => $dist_name ); |
85 | 85 | my $build = $fbmm->load_build('ffi', undef, 'ffi/_build'); |
149 | 149 | |
150 | 150 | =head1 VERSION |
151 | 151 | |
152 | version 1.32 | |
152 | version 1.33 | |
153 | 153 | |
154 | 154 | =head1 SYNOPSIS |
155 | 155 |
11 | 11 | }, bool => sub { 1 }, fallback => 1; |
12 | 12 | |
13 | 13 | # ABSTRACT: Platypus closure object |
14 | our $VERSION = '1.32'; # VERSION | |
14 | our $VERSION = '1.33'; # VERSION | |
15 | 15 | |
16 | 16 | |
17 | 17 | sub new |
66 | 66 | |
67 | 67 | package FFI::Platypus::ClosureData; |
68 | 68 | |
69 | our $VERSION = '1.32'; # VERSION | |
69 | our $VERSION = '1.33'; # VERSION | |
70 | 70 | |
71 | 71 | 1; |
72 | 72 | |
82 | 82 | |
83 | 83 | =head1 VERSION |
84 | 84 | |
85 | version 1.32 | |
85 | version 1.33 | |
86 | 86 | |
87 | 87 | =head1 SYNOPSIS |
88 | 88 |
6 | 6 | use FFI::Platypus; |
7 | 7 | |
8 | 8 | # ABSTRACT: Define constants in C space for Perl |
9 | our $VERSION = '1.32'; # VERSION | |
9 | our $VERSION = '1.33'; # VERSION | |
10 | 10 | |
11 | 11 | |
12 | 12 | { |
65 | 65 | |
66 | 66 | =head1 VERSION |
67 | 67 | |
68 | version 1.32 | |
68 | version 1.33 | |
69 | 69 | |
70 | 70 | =head1 SYNOPSIS |
71 | 71 |
9 | 9 | push @EXPORT, grep /RTLD_/, keys %FFI::Platypus::DL::; |
10 | 10 | |
11 | 11 | # ABSTRACT: Slightly non-portable interface to libdl |
12 | our $VERSION = '1.32'; # VERSION | |
12 | our $VERSION = '1.33'; # VERSION | |
13 | 13 | |
14 | 14 | |
15 | 15 | 1; |
26 | 26 | |
27 | 27 | =head1 VERSION |
28 | 28 | |
29 | version 1.32 | |
29 | version 1.33 | |
30 | 30 | |
31 | 31 | =head1 SYNOPSIS |
32 | 32 |
0 | package FFI::Platypus::Declare; | |
1 | ||
2 | use strict; | |
3 | use warnings; | |
4 | use 5.008004; | |
5 | use Carp (); | |
6 | use FFI::Platypus; | |
7 | ||
8 | # ABSTRACT: Declarative interface to FFI::Platypus | |
9 | our $VERSION = '1.32'; # VERSION | |
10 | ||
11 | ||
12 | our $ffi = {}; | |
13 | our $types = {}; | |
14 | ||
15 | sub _ffi_object | |
16 | { | |
17 | my($package, $filename) = caller(1); | |
18 | $ffi->{$package} ||= FFI::Platypus->new->package($package,$filename); | |
19 | } | |
20 | ||
21 | ||
22 | sub lib (@) | |
23 | { | |
24 | _ffi_object->lib(@_); | |
25 | } | |
26 | ||
27 | ||
28 | sub type ($;$) | |
29 | { | |
30 | _ffi_object->type(@_); | |
31 | } | |
32 | ||
33 | ||
34 | sub custom_type ($$) | |
35 | { | |
36 | _ffi_object->custom_type(@_); | |
37 | } | |
38 | ||
39 | ||
40 | sub load_custom_type ($$;@) | |
41 | { | |
42 | _ffi_object->load_custom_type(@_); | |
43 | } | |
44 | ||
45 | ||
46 | sub type_meta($) | |
47 | { | |
48 | _ffi_object->type_meta(@_); | |
49 | } | |
50 | ||
51 | ||
52 | my $inner_counter = 0; | |
53 | ||
54 | sub attach ($$$;$$) | |
55 | { | |
56 | my $wrapper; | |
57 | $wrapper = pop if ref($_[-1]) eq 'CODE'; | |
58 | my($name, $args, $ret, $proto) = @_; | |
59 | ||
60 | my($symbol_name, $perl_name) = ref $name ? (@$name) : ($name, $name); | |
61 | my $function = _ffi_object->function($symbol_name, $args, $ret, $wrapper); | |
62 | $function->attach($perl_name, $proto); | |
63 | (); | |
64 | } | |
65 | ||
66 | ||
67 | sub closure (&) | |
68 | { | |
69 | my($coderef) = @_; | |
70 | require FFI::Platypus::Closure; | |
71 | FFI::Platypus::Closure->new($coderef); | |
72 | } | |
73 | ||
74 | ||
75 | sub sticky ($) | |
76 | { | |
77 | my($closure) = @_; | |
78 | Carp::croak("usage: sticky \$closure") | |
79 | unless defined $closure && ref($closure) eq 'FFI::Platypus::Closure'; | |
80 | $closure->sticky; | |
81 | $closure; | |
82 | } | |
83 | ||
84 | ||
85 | sub cast ($$$) | |
86 | { | |
87 | _ffi_object->cast(@_); | |
88 | } | |
89 | ||
90 | ||
91 | sub attach_cast ($$$) | |
92 | { | |
93 | my($name, $type1, $type2) = @_; | |
94 | my $caller = caller; | |
95 | $name = join '::', $caller, $name; | |
96 | _ffi_object->attach_cast($name, $type1, $type2); | |
97 | } | |
98 | ||
99 | ||
100 | sub sizeof ($) | |
101 | { | |
102 | _ffi_object->sizeof($_[0]); | |
103 | } | |
104 | ||
105 | ||
106 | sub lang ($) | |
107 | { | |
108 | _ffi_object->lang($_[0]); | |
109 | } | |
110 | ||
111 | ||
112 | sub abi ($) | |
113 | { | |
114 | _ffi_object->abi($_[0]); | |
115 | } | |
116 | ||
117 | sub import | |
118 | { | |
119 | my $caller = caller; | |
120 | shift; # class | |
121 | ||
122 | foreach my $arg (@_) | |
123 | { | |
124 | if(ref $arg) | |
125 | { | |
126 | if($arg->[0] =~ /::/) | |
127 | { | |
128 | _ffi_object->load_custom_type(@$arg); | |
129 | no strict 'refs'; | |
130 | *{join '::', $caller, $arg->[1]} = sub () { $arg->[1] }; | |
131 | } | |
132 | else | |
133 | { | |
134 | _ffi_object->type(@$arg); | |
135 | no strict 'refs'; | |
136 | *{join '::', $caller, $arg->[1]} = sub () { $arg->[0] }; | |
137 | } | |
138 | } | |
139 | else | |
140 | { | |
141 | _ffi_object->type($arg); | |
142 | no strict 'refs'; | |
143 | *{join '::', $caller, $arg} = sub () { $arg }; | |
144 | } | |
145 | } | |
146 | ||
147 | no strict 'refs'; | |
148 | *{join '::', $caller, 'lib'} = \&lib; | |
149 | *{join '::', $caller, 'type'} = \&type; | |
150 | *{join '::', $caller, 'type_meta'} = \&type_meta; | |
151 | *{join '::', $caller, 'custom_type'} = \&custom_type; | |
152 | *{join '::', $caller, 'load_custom_type'} = \&load_custom_type; | |
153 | *{join '::', $caller, 'attach'} = \&attach; | |
154 | *{join '::', $caller, 'closure'} = \&closure; | |
155 | *{join '::', $caller, 'sticky'} = \&sticky; | |
156 | *{join '::', $caller, 'cast'} = \&cast; | |
157 | *{join '::', $caller, 'attach_cast'} = \&attach_cast; | |
158 | *{join '::', $caller, 'sizeof'} = \&sizeof; | |
159 | *{join '::', $caller, 'lang'} = \⟨ | |
160 | *{join '::', $caller, 'abi'} = \&abi; | |
161 | } | |
162 | ||
163 | 1; | |
164 | ||
165 | __END__ | |
166 | ||
167 | =pod | |
168 | ||
169 | =encoding UTF-8 | |
170 | ||
171 | =head1 NAME | |
172 | ||
173 | FFI::Platypus::Declare - Declarative interface to FFI::Platypus | |
174 | ||
175 | =head1 VERSION | |
176 | ||
177 | version 1.32 | |
178 | ||
179 | =head1 SYNOPSIS | |
180 | ||
181 | use FFI::Platypus::Declare 'string', 'int'; | |
182 | ||
183 | lib undef; # use libc | |
184 | attach puts => [string] => int; | |
185 | ||
186 | puts("hello world"); | |
187 | ||
188 | =head1 DESCRIPTION | |
189 | ||
190 | This module is officially B<discouraged>. The idea was to provide a | |
191 | simpler declarative interface without the need of (directly) creating | |
192 | an L<FFI::Platypus> instance. In practice it is almost as complicated | |
193 | and makes it difficult to upgrade to the proper OO interface if the | |
194 | need arises. I have stopped using it mainly for this reason. It will | |
195 | remain as part of the Platypus core distribution to keep old code working, | |
196 | but you are encouraged to write new code using the OO interface. | |
197 | Alternatively, you can try the Perl 6 inspired L<NativeCall>, which | |
198 | provides most of the goals this module was intended for (that is | |
199 | a simple interface at the cost of some power), without much of the | |
200 | complexity. The remainder of this document describes the interface. | |
201 | ||
202 | This module provides a declarative interface to L<FFI::Platypus>. It | |
203 | provides a more concise interface at the cost of a little less power, | |
204 | and a little more namespace pollution. | |
205 | ||
206 | Any strings passed into the C<use> line will be declared as types and | |
207 | exported as constants into your namespace, so that you can use them | |
208 | without quotation marks. | |
209 | ||
210 | Aliases can be declared using a list reference: | |
211 | ||
212 | use FFI::Platypus [ 'int[48]' => 'my_integer_array' ]; | |
213 | ||
214 | Custom types can also be declared as a list reference (the type name | |
215 | must include a ::): | |
216 | ||
217 | use FFI::Platypus [ '::StringPointer' => 'my_string_pointer' ]; | |
218 | # short for FFI::Platypus::Type::StringPointer | |
219 | ||
220 | =head1 FUNCTIONS | |
221 | ||
222 | All functions are exported into your namespace. If you do not want that, | |
223 | then use the OO interface (see L<FFI::Platypus>). | |
224 | ||
225 | =head2 lib | |
226 | ||
227 | lib $libpath; | |
228 | ||
229 | Specify one or more dynamic libraries to search for symbols. If you are | |
230 | unsure of the location / version of the library then you can use | |
231 | L<FFI::CheckLib#find_lib>. | |
232 | ||
233 | =head2 type | |
234 | ||
235 | type $type; | |
236 | type $type = $alias; | |
237 | ||
238 | Declare the given type. | |
239 | ||
240 | Examples: | |
241 | ||
242 | type 'uint8'; # only really checks that uint8 is a valid type | |
243 | type 'uint8' => 'my_unsigned_int_8'; | |
244 | ||
245 | =head2 custom_type | |
246 | ||
247 | custom_type $alias => \%args; | |
248 | ||
249 | Declare the given custom type. See L<FFI::Platypus::Type#Custom-Types> | |
250 | for details. | |
251 | ||
252 | =head2 load_custom_type | |
253 | ||
254 | load_custom_type $name => $alias, @type_args; | |
255 | ||
256 | Load the custom type defined in the module I<$name>, and make an alias | |
257 | with the name I<$alias>. If the custom type requires any arguments, they | |
258 | may be passed in as I<@type_args>. See L<FFI::Platypus::Type#Custom-Types> | |
259 | for details. | |
260 | ||
261 | If I<$name> contains C<::> then it will be assumed to be a fully | |
262 | qualified package name. If not, then C<FFI::Platypus::Type::> will be | |
263 | prepended to it. | |
264 | ||
265 | =head2 type_meta | |
266 | ||
267 | my $meta = type_meta $type; | |
268 | ||
269 | Get the type meta data for the given type. | |
270 | ||
271 | Example: | |
272 | ||
273 | my $meta = type_meta 'int'; | |
274 | ||
275 | =head2 attach | |
276 | ||
277 | attach $name => \@argument_types => $return_type; | |
278 | attach [$c_name => $perl_name] => \@argument_types => $return_type; | |
279 | attach [$address => $perl_name] => \@argument_types => $return_type; | |
280 | ||
281 | Find and attach a C function as a Perl function as a real live xsub. | |
282 | ||
283 | If just one I<$name> is given, then the function will be attached in | |
284 | Perl with the same name as it has in C. The second form allows you to | |
285 | give the Perl function a different name. You can also provide a memory | |
286 | address (the third form) of a function to attach. | |
287 | ||
288 | Examples: | |
289 | ||
290 | attach 'my_function', ['uint8'] => 'string'; | |
291 | attach ['my_c_function_name' => 'my_perl_function_name'], ['uint8'] => 'string'; | |
292 | my $string1 = my_function($int); | |
293 | my $string2 = my_perl_function_name($int); | |
294 | ||
295 | =head2 closure | |
296 | ||
297 | my $closure = closure $codeblock; | |
298 | ||
299 | Create a closure that can be passed into a C function. For details on closures, see L<FFI::Platypus::Type#Closures>. | |
300 | ||
301 | Example: | |
302 | ||
303 | my $closure1 = closure { return $_[0] * 2 }; | |
304 | my $closure2 = closure sub { return $_[0] * 4 }; | |
305 | ||
306 | =head2 sticky | |
307 | ||
308 | my $closure = sticky closure $codeblock; | |
309 | ||
310 | Keyword to indicate the closure should not be deallocated for the life | |
311 | of the current process. | |
312 | ||
313 | If you pass a closure into a C function without saving a reference to it | |
314 | like this: | |
315 | ||
316 | foo(closure { ... }); # BAD | |
317 | ||
318 | Perl will not see any references to it and try to free it immediately. | |
319 | (this has to do with the way Perl and C handle responsibilities for | |
320 | memory allocation differently). One fix for this is to make sure the | |
321 | closure remains in scope using either C<my> or C<our>. If you know the | |
322 | closure will need to remain in existence for the life of the process (or | |
323 | if you do not care about leaking memory), then you can add the sticky | |
324 | keyword to tell L<FFI::Platypus> to keep the thing in memory. | |
325 | ||
326 | foo(sticky closure { ... }); # OKAY | |
327 | ||
328 | =head2 cast | |
329 | ||
330 | my $converted_value = cast $original_type, $converted_type, $original_value; | |
331 | ||
332 | The C<cast> function converts an existing I<$original_value> of type | |
333 | I<$original_type> into one of type I<$converted_type>. Not all types | |
334 | are supported, so care must be taken. For example, to get the address | |
335 | of a string, you can do this: | |
336 | ||
337 | my $address = cast 'string' => 'opaque', $string_value; | |
338 | ||
339 | =head2 attach_cast | |
340 | ||
341 | attach_cast "cast_name", $original_type, $converted_type; | |
342 | my $converted_value = cast_name($original_value); | |
343 | ||
344 | This function creates a subroutine which can be used to convert | |
345 | variables just like the L<cast|FFI::Platypus::Declare#cast> function | |
346 | above. The above synopsis is roughly equivalent to this: | |
347 | ||
348 | sub cast_name { cast($original_type, $converted_type, $_[0]) } | |
349 | my $converted_value = cast_name($original_value); | |
350 | ||
351 | Except that the L<attach_cast|FFI::Platypus::Declare#attach_cast> | |
352 | variant will be much faster if called multiple times since the cast does | |
353 | not need to be dynamically allocated on each instance. | |
354 | ||
355 | =head2 sizeof | |
356 | ||
357 | my $size = sizeof $type; | |
358 | ||
359 | Returns the total size of the given type. For example to get the size | |
360 | of an integer: | |
361 | ||
362 | my $intsize = sizeof 'int'; # usually 4 or 8 depending on platform | |
363 | ||
364 | You can also get the size of arrays | |
365 | ||
366 | my $intarraysize = sizeof 'int[64]'; | |
367 | ||
368 | Keep in mind that "pointer" types will always be the pointer / word size | |
369 | for the platform that you are using. This includes strings, opaque and | |
370 | pointers to other types. | |
371 | ||
372 | This function is not very fast, so you might want to save this value as | |
373 | a constant, particularly if you need the size in a loop with many | |
374 | iterations. | |
375 | ||
376 | =head2 lang | |
377 | ||
378 | lang $language; | |
379 | ||
380 | Specifies the foreign language that you will be interfacing with. The | |
381 | default is C. The foreign language specified with this attribute | |
382 | changes the default native types (for example, if you specify | |
383 | L<Rust|FFI::Platypus::Lang::Rust>, you will get C<i32> as an alias for | |
384 | C<sint32> instead of C<int> as you do with L<C|FFI::Platypus::Lang::C>). | |
385 | ||
386 | In the future this may attribute may offer hints when doing demangling | |
387 | of languages that require it like L<C++|FFI::Platypus::Lang::CPP>. | |
388 | ||
389 | =head2 abi | |
390 | ||
391 | abi $abi; | |
392 | ||
393 | Set the ABI or calling convention for use in subsequent calls | |
394 | to L</attach>. May be either a string name or integer value | |
395 | from L<FFI::Platypus#abis>. | |
396 | ||
397 | =head1 SEE ALSO | |
398 | ||
399 | =over 4 | |
400 | ||
401 | =item L<FFI::Platypus> | |
402 | ||
403 | Object oriented interface to Platypus. | |
404 | ||
405 | =item L<FFI::Platypus::Type> | |
406 | ||
407 | Type definitions for Platypus. | |
408 | ||
409 | =item L<FFI::Platypus::API> | |
410 | ||
411 | Custom types API for Platypus. | |
412 | ||
413 | =item L<FFI::Platypus::Memory> | |
414 | ||
415 | memory functions for FFI. | |
416 | ||
417 | =item L<FFI::CheckLib> | |
418 | ||
419 | Find dynamic libraries in a portable way. | |
420 | ||
421 | =item L<FFI::TinyCC> | |
422 | ||
423 | JIT compiler for FFI. | |
424 | ||
425 | =back | |
426 | ||
427 | =head1 AUTHOR | |
428 | ||
429 | Author: Graham Ollis E<lt>plicease@cpan.orgE<gt> | |
430 | ||
431 | Contributors: | |
432 | ||
433 | Bakkiaraj Murugesan (bakkiaraj) | |
434 | ||
435 | Dylan Cali (calid) | |
436 | ||
437 | pipcet | |
438 | ||
439 | Zaki Mughal (zmughal) | |
440 | ||
441 | Fitz Elliott (felliott) | |
442 | ||
443 | Vickenty Fesunov (vyf) | |
444 | ||
445 | Gregor Herrmann (gregoa) | |
446 | ||
447 | Shlomi Fish (shlomif) | |
448 | ||
449 | Damyan Ivanov | |
450 | ||
451 | Ilya Pavlov (Ilya33) | |
452 | ||
453 | Petr Pisar (ppisar) | |
454 | ||
455 | Mohammad S Anwar (MANWAR) | |
456 | ||
457 | Håkon Hægland (hakonhagland, HAKONH) | |
458 | ||
459 | Meredith (merrilymeredith, MHOWARD) | |
460 | ||
461 | Diab Jerius (DJERIUS) | |
462 | ||
463 | =head1 COPYRIGHT AND LICENSE | |
464 | ||
465 | This software is copyright (c) 2015,2016,2017,2018,2019,2020 by Graham Ollis. | |
466 | ||
467 | This is free software; you can redistribute it and/or modify it under | |
468 | the same terms as the Perl 5 programming language system itself. | |
469 | ||
470 | =cut |
5 | 5 | use FFI::Platypus; |
6 | 6 | |
7 | 7 | # ABSTRACT: An FFI function object |
8 | our $VERSION = '1.32'; # VERSION | |
8 | our $VERSION = '1.33'; # VERSION | |
9 | 9 | |
10 | 10 | |
11 | 11 | use overload '&{}' => sub { |
126 | 126 | |
127 | 127 | =head1 VERSION |
128 | 128 | |
129 | version 1.32 | |
129 | version 1.33 | |
130 | 130 | |
131 | 131 | =head1 SYNOPSIS |
132 | 132 |
11 | 11 | our @EXPORT = grep /^FFI_PL/, keys %FFI::Platypus::Internal::; |
12 | 12 | |
13 | 13 | # ABSTRACT: For internal use only |
14 | our $VERSION = '1.32'; # VERSION | |
14 | our $VERSION = '1.33'; # VERSION | |
15 | 15 | |
16 | 16 | |
17 | 17 | 1; |
28 | 28 | |
29 | 29 | =head1 VERSION |
30 | 30 | |
31 | version 1.32 | |
31 | version 1.33 | |
32 | 32 | |
33 | 33 | =head1 SYNOPSIS |
34 | 34 |
4 | 4 | use 5.008004; |
5 | 5 | |
6 | 6 | # ABSTRACT: Documentation and tools for using Platypus with the Assembly |
7 | our $VERSION = '1.32'; # VERSION | |
7 | our $VERSION = '1.33'; # VERSION | |
8 | 8 | |
9 | 9 | |
10 | 10 | sub native_type_map |
26 | 26 | |
27 | 27 | =head1 VERSION |
28 | 28 | |
29 | version 1.32 | |
29 | version 1.33 | |
30 | 30 | |
31 | 31 | =head1 SYNOPSIS |
32 | 32 |
4 | 4 | use 5.008004; |
5 | 5 | |
6 | 6 | # ABSTRACT: Documentation and tools for using Platypus with the C programming language |
7 | our $VERSION = '1.32'; # VERSION | |
7 | our $VERSION = '1.33'; # VERSION | |
8 | 8 | |
9 | 9 | |
10 | 10 | sub native_type_map |
27 | 27 | |
28 | 28 | =head1 VERSION |
29 | 29 | |
30 | version 1.32 | |
30 | version 1.33 | |
31 | 31 | |
32 | 32 | =head1 SYNOPSIS |
33 | 33 |
5 | 5 | use Config; |
6 | 6 | |
7 | 7 | # ABSTRACT: Documentation and tools for using Platypus with the Windows API |
8 | our $VERSION = '1.32'; # VERSION | |
8 | our $VERSION = '1.33'; # VERSION | |
9 | 9 | |
10 | 10 | |
11 | 11 | sub abi |
187 | 187 | |
188 | 188 | =head1 VERSION |
189 | 189 | |
190 | version 1.32 | |
190 | version 1.33 | |
191 | 191 | |
192 | 192 | =head1 SYNOPSIS |
193 | 193 |
4 | 4 | use 5.008004; |
5 | 5 | |
6 | 6 | # ABSTRACT: Language specific customizations |
7 | our $VERSION = '1.32'; # VERSION | |
7 | our $VERSION = '1.33'; # VERSION | |
8 | 8 | |
9 | 9 | |
10 | 10 | |
22 | 22 | |
23 | 23 | =head1 VERSION |
24 | 24 | |
25 | version 1.32 | |
25 | version 1.33 | |
26 | 26 | |
27 | 27 | =head1 SYNOPSIS |
28 | 28 |
4 | 4 | use 5.008004; |
5 | 5 | |
6 | 6 | # ABSTRACT: Legacy Platypus interfaces |
7 | our $VERSION = '1.32'; # VERSION | |
7 | our $VERSION = '1.33'; # VERSION | |
8 | 8 | |
9 | 9 | |
10 | 10 | package FFI::Platypus; |
77 | 77 | |
78 | 78 | =head1 VERSION |
79 | 79 | |
80 | version 1.32 | |
80 | version 1.33 | |
81 | 81 | |
82 | 82 | =head1 DESCRIPTION |
83 | 83 |
6 | 6 | use base qw( Exporter ); |
7 | 7 | |
8 | 8 | # ABSTRACT: Memory functions for FFI |
9 | our $VERSION = '1.32'; # VERSION | |
9 | our $VERSION = '1.33'; # VERSION | |
10 | 10 | |
11 | 11 | |
12 | 12 | our @EXPORT = qw( malloc free calloc realloc memcpy memset strdup strndup strcpy ); |
66 | 66 | |
67 | 67 | =head1 VERSION |
68 | 68 | |
69 | version 1.32 | |
69 | version 1.33 | |
70 | 70 | |
71 | 71 | =head1 SYNOPSIS |
72 | 72 |
4 | 4 | use 5.008004; |
5 | 5 | |
6 | 6 | # ABSTRACT: FFI support for structured records data |
7 | our $VERSION = '1.32'; # VERSION | |
7 | our $VERSION = '1.33'; # VERSION | |
8 | 8 | |
9 | 9 | |
10 | 10 | { |
82 | 82 | |
83 | 83 | =head1 VERSION |
84 | 84 | |
85 | version 1.32 | |
85 | version 1.33 | |
86 | 86 | |
87 | 87 | =head1 DESCRIPTION |
88 | 88 |
5 | 5 | use Carp qw( croak ); |
6 | 6 | |
7 | 7 | # ABSTRACT: Tied array interface for record array members |
8 | our $VERSION = '1.32'; # VERSION | |
8 | our $VERSION = '1.33'; # VERSION | |
9 | 9 | |
10 | 10 | |
11 | 11 | sub TIEARRAY |
62 | 62 | |
63 | 63 | =head1 VERSION |
64 | 64 | |
65 | version 1.32 | |
65 | version 1.33 | |
66 | 66 | |
67 | 67 | =head1 SYNOPSIS |
68 | 68 |
10 | 10 | our @EXPORT = qw( record_layout record_layout_1 ); |
11 | 11 | |
12 | 12 | # ABSTRACT: FFI support for structured records data |
13 | our $VERSION = '1.32'; # VERSION | |
13 | our $VERSION = '1.33'; # VERSION | |
14 | 14 | |
15 | 15 | |
16 | 16 | sub record_layout_1 |
199 | 199 | |
200 | 200 | =head1 VERSION |
201 | 201 | |
202 | version 1.32 | |
202 | version 1.33 | |
203 | 203 | |
204 | 204 | =head1 SYNOPSIS |
205 | 205 |
4 | 4 | use 5.008004; |
5 | 5 | use File::Spec; |
6 | 6 | |
7 | our $VERSION = '1.32'; # VERSION | |
7 | our $VERSION = '1.33'; # VERSION | |
8 | 8 | |
9 | 9 | sub dist_dir ($) |
10 | 10 | { |
63 | 63 | |
64 | 64 | =head1 VERSION |
65 | 65 | |
66 | version 1.32 | |
66 | version 1.33 | |
67 | 67 | |
68 | 68 | =head1 AUTHOR |
69 | 69 |
12 | 12 | use FFI::Platypus::Buffer qw( buffer_to_scalar ); |
13 | 13 | |
14 | 14 | # ABSTRACT: Convert string scalar to a buffer as a pointer / size_t combination |
15 | our $VERSION = '1.32'; # VERSION | |
15 | our $VERSION = '1.33'; # VERSION | |
16 | 16 | |
17 | 17 | |
18 | 18 | my @stack; |
60 | 60 | |
61 | 61 | =head1 VERSION |
62 | 62 | |
63 | version 1.32 | |
63 | version 1.33 | |
64 | 64 | |
65 | 65 | =head1 SYNOPSIS |
66 | 66 |
5 | 5 | use FFI::Platypus; |
6 | 6 | |
7 | 7 | # ABSTRACT: Platypus custom type for arrays of strings |
8 | our $VERSION = '1.32'; # VERSION | |
8 | our $VERSION = '1.33'; # VERSION | |
9 | 9 | |
10 | 10 | |
11 | 11 | use constant _incantation => |
124 | 124 | |
125 | 125 | =head1 VERSION |
126 | 126 | |
127 | version 1.32 | |
127 | version 1.33 | |
128 | 128 | |
129 | 129 | =head1 SYNOPSIS |
130 | 130 |
6 | 6 | use Scalar::Util qw( readonly ); |
7 | 7 | |
8 | 8 | # ABSTRACT: Convert a pointer to a string and back |
9 | our $VERSION = '1.32'; # VERSION | |
9 | our $VERSION = '1.33'; # VERSION | |
10 | 10 | |
11 | 11 | |
12 | 12 | use constant _incantation => |
75 | 75 | |
76 | 76 | =head1 VERSION |
77 | 77 | |
78 | version 1.32 | |
78 | version 1.33 | |
79 | 79 | |
80 | 80 | =head1 SYNOPSIS |
81 | 81 |
6 | 6 | require FFI::Platypus; |
7 | 7 | |
8 | 8 | # ABSTRACT: Defining types for FFI::Platypus |
9 | our $VERSION = '1.32'; # VERSION | |
9 | our $VERSION = '1.33'; # VERSION | |
10 | 10 | |
11 | 11 | # The TypeParser and Type classes are used internally ONLY and |
12 | 12 | # are not to be exposed to the user. External users should |
57 | 57 | |
58 | 58 | =head1 VERSION |
59 | 59 | |
60 | version 1.32 | |
60 | version 1.33 | |
61 | 61 | |
62 | 62 | =head1 SYNOPSIS |
63 | 63 | |
362 | 362 | |
363 | 363 | The main FAQ (L<FFI::Platypus/FAQ>) also has a discussion on dealing |
364 | 364 | with constants and enumerated types. |
365 | ||
366 | There is also a type plugin (L<FFI::Platypus::Type::Enum>) that can be helpful | |
367 | in writing interfaces that use enums. | |
365 | 368 | |
366 | 369 | =head3 Boolean types |
367 | 370 |
6 | 6 | use base qw( FFI::Platypus::TypeParser ); |
7 | 7 | |
8 | 8 | # ABSTRACT: FFI Type Parser Version Zero |
9 | our $VERSION = '1.32'; # VERSION | |
9 | our $VERSION = '1.33'; # VERSION | |
10 | 10 | |
11 | 11 | |
12 | 12 | our @CARP_NOT = qw( FFI::Platypus FFI::Platypus::TypeParser ); |
164 | 164 | |
165 | 165 | =head1 VERSION |
166 | 166 | |
167 | version 1.32 | |
167 | version 1.33 | |
168 | 168 | |
169 | 169 | =head1 SYNOPSIS |
170 | 170 |
6 | 6 | use base qw( FFI::Platypus::TypeParser ); |
7 | 7 | |
8 | 8 | # ABSTRACT: FFI Type Parser Version One |
9 | our $VERSION = '1.32'; # VERSION | |
9 | our $VERSION = '1.33'; # VERSION | |
10 | 10 | |
11 | 11 | |
12 | 12 | our @CARP_NOT = qw( FFI::Platypus FFI::Platypus::TypeParser ); |
290 | 290 | |
291 | 291 | =head1 VERSION |
292 | 292 | |
293 | version 1.32 | |
293 | version 1.33 | |
294 | 294 | |
295 | 295 | =head1 SYNOPSIS |
296 | 296 |
6 | 6 | use Carp qw( croak ); |
7 | 7 | |
8 | 8 | # ABSTRACT: FFI Type Parser |
9 | our $VERSION = '1.32'; # VERSION | |
9 | our $VERSION = '1.33'; # VERSION | |
10 | 10 | |
11 | 11 | |
12 | 12 | # The TypeParser and Type classes are used internally ONLY and |
111 | 111 | |
112 | 112 | =head1 VERSION |
113 | 113 | |
114 | version 1.32 | |
114 | version 1.33 | |
115 | 115 | |
116 | 116 | =head1 DESCRIPTION |
117 | 117 |
7 | 7 | use FFI::Platypus::Type; |
8 | 8 | |
9 | 9 | # ABSTRACT: Write Perl bindings to non-Perl libraries with FFI. No XS required. |
10 | our $VERSION = '1.32'; # VERSION | |
10 | our $VERSION = '1.33'; # VERSION | |
11 | 11 | |
12 | 12 | # Platypus Man, |
13 | 13 | # Platypus Man, |
582 | 582 | |
583 | 583 | =head1 VERSION |
584 | 584 | |
585 | version 1.32 | |
585 | version 1.33 | |
586 | 586 | |
587 | 587 | =head1 SYNOPSIS |
588 | 588 | |
2036 | 2036 | |
2037 | 2037 | For more details on enumerated types see L<FFI::Platypus::Type/"Enum types">. |
2038 | 2038 | |
2039 | There is also a type plugin (L<FFI::Platypus::Type::Enum>) that can be helpful | |
2040 | in writing interfaces that use enums. | |
2041 | ||
2039 | 2042 | =head2 Memory leaks |
2040 | 2043 | |
2041 | 2044 | There are a couple places where memory is allocated, but never deallocated that may |
8 | 8 | use FFI::Build::Platform; |
9 | 9 | |
10 | 10 | # ABSTRACT: Probe runner builder for FFI |
11 | our $VERSION = '1.32'; # VERSION | |
11 | our $VERSION = '1.33'; # VERSION | |
12 | 12 | |
13 | 13 | |
14 | 14 | sub new |
250 | 250 | |
251 | 251 | =head1 VERSION |
252 | 252 | |
253 | version 1.32 | |
253 | version 1.33 | |
254 | 254 | |
255 | 255 | =head1 SYNOPSIS |
256 | 256 |
4 | 4 | use 5.008004; |
5 | 5 | |
6 | 6 | # ABSTRACT: The results from a probe run. |
7 | our $VERSION = '1.32'; # VERSION | |
7 | our $VERSION = '1.33'; # VERSION | |
8 | 8 | |
9 | 9 | |
10 | 10 | sub new |
41 | 41 | |
42 | 42 | =head1 VERSION |
43 | 43 | |
44 | version 1.32 | |
44 | version 1.33 | |
45 | 45 | |
46 | 46 | =head1 SYNOPSIS |
47 | 47 |
6 | 6 | use FFI::Probe::Runner::Result; |
7 | 7 | |
8 | 8 | # ABSTRACT: Probe runner for FFI |
9 | our $VERSION = '1.32'; # VERSION | |
9 | our $VERSION = '1.33'; # VERSION | |
10 | 10 | |
11 | 11 | |
12 | 12 | sub new |
84 | 84 | |
85 | 85 | =head1 VERSION |
86 | 86 | |
87 | version 1.32 | |
87 | version 1.33 | |
88 | 88 | |
89 | 89 | =head1 SYNOPSIS |
90 | 90 |
11 | 11 | use FFI::Temp; |
12 | 12 | |
13 | 13 | # ABSTRACT: System detection and probing for FFI extensions. |
14 | our $VERSION = '1.32'; # VERSION | |
14 | our $VERSION = '1.33'; # VERSION | |
15 | 15 | |
16 | 16 | |
17 | 17 | sub new |
512 | 512 | |
513 | 513 | =head1 VERSION |
514 | 514 | |
515 | version 1.32 | |
515 | version 1.33 | |
516 | 516 | |
517 | 517 | =head1 SYNOPSIS |
518 | 518 |
7 | 7 | use File::Temp qw( tempdir ); |
8 | 8 | |
9 | 9 | # ABSTRACT: Temp Dir support for FFI::Platypus |
10 | our $VERSION = '1.32'; # VERSION | |
10 | our $VERSION = '1.33'; # VERSION | |
11 | 11 | |
12 | 12 | |
13 | 13 | # problem with vanilla File::Temp is that is often uses |
79 | 79 | |
80 | 80 | =head1 VERSION |
81 | 81 | |
82 | version 1.32 | |
82 | version 1.33 | |
83 | 83 | |
84 | 84 | =head1 DESCRIPTION |
85 | 85 |
16 | 16 | require_ok 'FFI::Platypus::Closure'; |
17 | 17 | require_ok 'FFI::Platypus::Constant'; |
18 | 18 | require_ok 'FFI::Platypus::DL'; |
19 | require_ok 'FFI::Platypus::Declare'; | |
20 | 19 | require_ok 'FFI::Platypus::Function'; |
21 | 20 | require_ok 'FFI::Platypus::Internal'; |
22 | 21 | require_ok 'FFI::Platypus::Lang'; |
56 | 55 | ok -f 't/ffi_platypus_closure.t', 'test for FFI::Platypus::Closure'; |
57 | 56 | ok -f 't/ffi_platypus_constant.t', 'test for FFI::Platypus::Constant'; |
58 | 57 | ok -f 't/ffi_platypus_dl.t', 'test for FFI::Platypus::DL'; |
59 | ok -f 't/ffi_platypus_declare.t', 'test for FFI::Platypus::Declare'; | |
60 | 58 | ok -f 't/ffi_platypus_function.t', 'test for FFI::Platypus::Function'; |
61 | 59 | ok -f 't/ffi_platypus_internal.t', 'test for FFI::Platypus::Internal'; |
62 | 60 | ok -f 't/ffi_platypus_lang.t', 'test for FFI::Platypus::Lang'; |
0 | use strict; | |
1 | use warnings; | |
2 | use Test::More; | |
3 | use FFI::CheckLib; | |
4 | use FFI::Platypus::Declare; | |
5 | ||
6 | my $libtest = find_lib lib => 'test', symbol => 'f0', libpath => 't/ffi'; | |
7 | ||
8 | subtest normal => sub { | |
9 | ||
10 | { package Normal; | |
11 | ||
12 | use FFI::Platypus::Declare; | |
13 | ||
14 | lib $libtest; | |
15 | attach 'f0', ['uint8'] => 'uint8'; | |
16 | attach [f0 => 'f1'], ['uint8'] => 'uint8'; | |
17 | ||
18 | attach [f0 => 'f0_wrap'] => ['uint8'] => 'uint8' => sub { | |
19 | my($inner, $value) = @_; | |
20 | $inner->($value+1)+2; | |
21 | }; | |
22 | ||
23 | attach [f0 => 'f0_wrap2'] => ['uint8'] => 'uint8' => '$' => sub { | |
24 | my($inner, $value) = @_; | |
25 | $inner->($value+1)+2; | |
26 | }; | |
27 | } | |
28 | ||
29 | is Normal::f0(22), 22, 'f0(22) = 22'; | |
30 | is Normal::f1(22), 22, 'f1(22) = 22'; | |
31 | is Normal::f0_wrap(22), 25, 'f0_wrap(22) = 25'; | |
32 | is Normal::f0_wrap2(22), 25, 'f0_wrap2(22) = 25'; | |
33 | }; | |
34 | ||
35 | subtest prototype => sub { | |
36 | ||
37 | my $value = eval q{ | |
38 | package ProtoType; | |
39 | ||
40 | use FFI::Platypus::Declare; | |
41 | ||
42 | BEGIN { | |
43 | lib $libtest; | |
44 | attach(f0 => ['uint8'] => 'uint8' => '$'); | |
45 | } | |
46 | ||
47 | f0 22; | |
48 | }; | |
49 | ||
50 | is $@, '', 'no compile error'; | |
51 | is $value, 22, 'f(22) = 22'; | |
52 | ||
53 | }; | |
54 | ||
55 | subtest 'with type aliases' => sub { | |
56 | ||
57 | { package WithTypeAliases; | |
58 | ||
59 | use FFI::Platypus::Declare | |
60 | 'string', | |
61 | [int => 'myint']; | |
62 | ||
63 | lib $libtest; | |
64 | attach [my_atoi=>'atoi'], [string] => myint; | |
65 | } | |
66 | ||
67 | is WithTypeAliases::atoi("42"), 42, 'atoi("42") = 42'; | |
68 | }; | |
69 | ||
70 | subtest 'simple closure test' => sub { | |
71 | ||
72 | { package ClosureSimple; | |
73 | ||
74 | use FFI::Platypus::Declare; | |
75 | ||
76 | our $closure = closure { $_[0]+1 }; | |
77 | } | |
78 | ||
79 | isa_ok $ClosureSimple::closure, 'FFI::Platypus::Closure'; | |
80 | is $ClosureSimple::closure->(1), 2, 'closure.(1) = 2'; | |
81 | }; | |
82 | ||
83 | subtest 'abis' => sub { | |
84 | ||
85 | my %abis = %{ FFI::Platypus->abis }; | |
86 | ||
87 | ok defined $abis{default_abi}, 'has a default ABI'; | |
88 | ||
89 | foreach my $abi (keys %abis) | |
90 | { | |
91 | subtest $abi => sub { | |
92 | eval { abi $abi }; | |
93 | is $@, '', 'string'; | |
94 | eval { abi $abis{$abi} }; | |
95 | is $@, '', 'integer'; | |
96 | }; | |
97 | } | |
98 | ||
99 | subtest 'bogus' => sub { | |
100 | eval { abi 'bogus' }; | |
101 | like $@, qr{no such ABI: bogus}, 'string'; | |
102 | eval { abi 999999 }; | |
103 | like $@, qr{no such ABI: 999999}, 'integer'; | |
104 | }; | |
105 | }; | |
106 | ||
107 | subtest 'lang' => sub { | |
108 | ||
109 | subtest C => sub { | |
110 | ||
111 | package | |
112 | Test1; | |
113 | ||
114 | use Test::More; | |
115 | use FFI::Platypus::Declare; | |
116 | ||
117 | eval { type 'int' }; | |
118 | is $@, '', 'int is an okay type'; | |
119 | eval { type 'foo_t' }; | |
120 | isnt $@, '', 'foo_t is not an okay type'; | |
121 | note $@; | |
122 | eval { type 'sint16' }; | |
123 | is $@, '', 'sint16 is an okay type'; | |
124 | ||
125 | }; | |
126 | ||
127 | subtest 'Foo constructor' => sub { | |
128 | ||
129 | package | |
130 | FFI::Platypus::Lang::Foo; | |
131 | ||
132 | sub native_type_map | |
133 | { | |
134 | { | |
135 | foo_t => 'sint16', | |
136 | bar_t => 'uint32', | |
137 | } | |
138 | } | |
139 | ||
140 | package | |
141 | Test2; | |
142 | ||
143 | use Test::More; | |
144 | use FFI::Platypus::Declare; | |
145 | ||
146 | lang 'Foo'; | |
147 | ||
148 | eval { type 'int' }; | |
149 | isnt $@, '', 'int is not an okay type'; | |
150 | note $@; | |
151 | eval { type 'foo_t' }; | |
152 | is $@, '', 'foo_t is an okay type'; | |
153 | eval { type 'sint16' }; | |
154 | is $@, '', 'sint16 is an okay type'; | |
155 | ||
156 | is sizeof('foo_t'), 2, 'sizeof foo_t = 2'; | |
157 | is sizeof('bar_t'), 4, 'sizeof foo_t = 4'; | |
158 | ||
159 | }; | |
160 | }; | |
161 | ||
162 | subtest 'sizeof' => sub { | |
163 | is sizeof 'uint32', 4, 'sizeof uint32 = 4'; | |
164 | is sizeof 'uint32[2]', 8, 'sizeof uint32[2] = 8'; | |
165 | }; | |
166 | ||
167 | subtest 'sticky' => sub { | |
168 | package Foo; | |
169 | ||
170 | use Test::More; | |
171 | use FFI::Platypus::Declare | |
172 | qw( uint8 void ), | |
173 | ['(uint8)->uint8' => 'closure_t']; | |
174 | ||
175 | lib $libtest; | |
176 | ||
177 | attach [uint8_set_closure => 'set_closure'] => [closure_t] => void; | |
178 | attach [uint8_call_closure => 'call_closure'] => [uint8] => uint8; | |
179 | ||
180 | set_closure(sticky closure { $_[0] * 2 }); | |
181 | is call_closure(2), 4, 'call_closure(2) = 4'; | |
182 | }; | |
183 | ||
184 | subtest 'cast' => sub { | |
185 | package Bar; | |
186 | ||
187 | use Test::More; | |
188 | use FFI::Platypus::Declare; | |
189 | ||
190 | lib $libtest; | |
191 | ||
192 | attach string_matches_foobarbaz => ['opaque'] => 'int'; | |
193 | attach string_return_foobarbaz => [] => 'opaque'; | |
194 | attach string_set_closure => ['opaque'] => 'void'; | |
195 | attach string_call_closure => ['string'] => 'void'; | |
196 | ||
197 | subtest 'cast from string to pointer' => sub { | |
198 | my $string = "foobarbaz"; | |
199 | my $pointer = cast string => opaque => $string; | |
200 | ||
201 | is string_matches_foobarbaz($pointer), 1, 'dynamic'; | |
202 | ||
203 | attach_cast cast1 => string => 'opaque'; | |
204 | my $pointer2 = cast1($string); | |
205 | ||
206 | is string_matches_foobarbaz($pointer2), 1, 'static'; | |
207 | ||
208 | }; | |
209 | ||
210 | subtest 'cast from pointer to string' => sub { | |
211 | my $pointer = string_return_foobarbaz(); | |
212 | my $string = cast opaque => string => $pointer; | |
213 | ||
214 | is $string, "foobarbaz", "dynamic"; | |
215 | ||
216 | attach_cast cast2 => pointer => 'string'; | |
217 | my $string2 = cast2($pointer); | |
218 | ||
219 | is $string2, "foobarbaz", "static"; | |
220 | ||
221 | }; | |
222 | ||
223 | subtest 'cast closure to opaque' => sub { | |
224 | my $testname = 'dynamic'; | |
225 | ||
226 | my $closure = closure { is $_[0], "testvalue", $testname }; | |
227 | my $pointer = cast '(string)->void' => opaque => $closure; | |
228 | ||
229 | string_set_closure($pointer); | |
230 | string_call_closure("testvalue"); | |
231 | ||
232 | attach_cast 'cast3', '(string)->void' => 'opaque'; | |
233 | my $pointer2 = cast3($closure); | |
234 | ||
235 | $testname = 'static'; | |
236 | string_set_closure($pointer2); | |
237 | string_call_closure("testvalue"); | |
238 | }; | |
239 | }; | |
240 | ||
241 | done_testing; |