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 | |
# VERSION
|
10 | |
|
11 | |
=head1 SYNOPSIS
|
12 | |
|
13 | |
use FFI::Platypus::Declare 'string', 'int';
|
14 | |
|
15 | |
lib undef; # use libc
|
16 | |
attach puts => [string] => int;
|
17 | |
|
18 | |
puts("hello world");
|
19 | |
|
20 | |
=head1 DESCRIPTION
|
21 | |
|
22 | |
This module is officially B<discouraged>. The idea was to provide a
|
23 | |
simpler declarative interface without the need of (directly) creating
|
24 | |
an L<FFI::Platypus> instance. In practice it is almost as complicated
|
25 | |
and makes it difficult to upgrade to the proper OO interface if the
|
26 | |
need arises. I have stopped using it mainly for this reason. It will
|
27 | |
remain as part of the Platypus core distribution to keep old code working,
|
28 | |
but you are encouraged to write new code using the OO interface.
|
29 | |
Alternatively, you can try the Perl 6 inspired L<NativeCall>, which
|
30 | |
provides most of the goals this module was intended for (that is
|
31 | |
a simple interface at the cost of some power), without much of the
|
32 | |
complexity. The remainder of this document describes the interface.
|
33 | |
|
34 | |
This module provides a declarative interface to L<FFI::Platypus>. It
|
35 | |
provides a more concise interface at the cost of a little less power,
|
36 | |
and a little more namespace pollution.
|
37 | |
|
38 | |
Any strings passed into the C<use> line will be declared as types and
|
39 | |
exported as constants into your namespace, so that you can use them
|
40 | |
without quotation marks.
|
41 | |
|
42 | |
Aliases can be declared using a list reference:
|
43 | |
|
44 | |
use FFI::Platypus [ 'int[48]' => 'my_integer_array' ];
|
45 | |
|
46 | |
Custom types can also be declared as a list reference (the type name
|
47 | |
must include a ::):
|
48 | |
|
49 | |
use FFI::Platypus [ '::StringPointer' => 'my_string_pointer' ];
|
50 | |
# short for FFI::Platypus::Type::StringPointer
|
51 | |
|
52 | |
=cut
|
53 | |
|
54 | |
our $ffi = {};
|
55 | |
our $types = {};
|
56 | |
|
57 | |
sub _ffi_object
|
58 | |
{
|
59 | |
my($package, $filename) = caller(1);
|
60 | |
$ffi->{$package} ||= FFI::Platypus->new->package($package,$filename);
|
61 | |
}
|
62 | |
|
63 | |
=head1 FUNCTIONS
|
64 | |
|
65 | |
All functions are exported into your namespace. If you do not want that,
|
66 | |
then use the OO interface (see L<FFI::Platypus>).
|
67 | |
|
68 | |
=head2 lib
|
69 | |
|
70 | |
lib $libpath;
|
71 | |
|
72 | |
Specify one or more dynamic libraries to search for symbols. If you are
|
73 | |
unsure of the location / version of the library then you can use
|
74 | |
L<FFI::CheckLib#find_lib>.
|
75 | |
|
76 | |
=cut
|
77 | |
|
78 | |
sub lib (@)
|
79 | |
{
|
80 | |
_ffi_object->lib(@_);
|
81 | |
}
|
82 | |
|
83 | |
=head2 type
|
84 | |
|
85 | |
type $type;
|
86 | |
type $type = $alias;
|
87 | |
|
88 | |
Declare the given type.
|
89 | |
|
90 | |
Examples:
|
91 | |
|
92 | |
type 'uint8'; # only really checks that uint8 is a valid type
|
93 | |
type 'uint8' => 'my_unsigned_int_8';
|
94 | |
|
95 | |
=cut
|
96 | |
|
97 | |
sub type ($;$)
|
98 | |
{
|
99 | |
_ffi_object->type(@_);
|
100 | |
}
|
101 | |
|
102 | |
=head2 custom_type
|
103 | |
|
104 | |
custom_type $alias => \%args;
|
105 | |
|
106 | |
Declare the given custom type. See L<FFI::Platypus::Type#Custom-Types>
|
107 | |
for details.
|
108 | |
|
109 | |
=cut
|
110 | |
|
111 | |
sub custom_type ($$)
|
112 | |
{
|
113 | |
_ffi_object->custom_type(@_);
|
114 | |
}
|
115 | |
|
116 | |
=head2 load_custom_type
|
117 | |
|
118 | |
load_custom_type $name => $alias, @type_args;
|
119 | |
|
120 | |
Load the custom type defined in the module I<$name>, and make an alias
|
121 | |
with the name I<$alias>. If the custom type requires any arguments, they
|
122 | |
may be passed in as I<@type_args>. See L<FFI::Platypus::Type#Custom-Types>
|
123 | |
for details.
|
124 | |
|
125 | |
If I<$name> contains C<::> then it will be assumed to be a fully
|
126 | |
qualified package name. If not, then C<FFI::Platypus::Type::> will be
|
127 | |
prepended to it.
|
128 | |
|
129 | |
=cut
|
130 | |
|
131 | |
sub load_custom_type ($$;@)
|
132 | |
{
|
133 | |
_ffi_object->load_custom_type(@_);
|
134 | |
}
|
135 | |
|
136 | |
=head2 type_meta
|
137 | |
|
138 | |
my $meta = type_meta $type;
|
139 | |
|
140 | |
Get the type meta data for the given type.
|
141 | |
|
142 | |
Example:
|
143 | |
|
144 | |
my $meta = type_meta 'int';
|
145 | |
|
146 | |
=cut
|
147 | |
|
148 | |
sub type_meta($)
|
149 | |
{
|
150 | |
_ffi_object->type_meta(@_);
|
151 | |
}
|
152 | |
|
153 | |
=head2 attach
|
154 | |
|
155 | |
attach $name => \@argument_types => $return_type;
|
156 | |
attach [$c_name => $perl_name] => \@argument_types => $return_type;
|
157 | |
attach [$address => $perl_name] => \@argument_types => $return_type;
|
158 | |
|
159 | |
Find and attach a C function as a Perl function as a real live xsub.
|
160 | |
|
161 | |
If just one I<$name> is given, then the function will be attached in
|
162 | |
Perl with the same name as it has in C. The second form allows you to
|
163 | |
give the Perl function a different name. You can also provide a memory
|
164 | |
address (the third form) of a function to attach.
|
165 | |
|
166 | |
Examples:
|
167 | |
|
168 | |
attach 'my_function', ['uint8'] => 'string';
|
169 | |
attach ['my_c_function_name' => 'my_perl_function_name'], ['uint8'] => 'string';
|
170 | |
my $string1 = my_function($int);
|
171 | |
my $string2 = my_perl_function_name($int);
|
172 | |
|
173 | |
=cut
|
174 | |
|
175 | |
my $inner_counter = 0;
|
176 | |
|
177 | |
sub attach ($$$;$$)
|
178 | |
{
|
179 | |
my $wrapper;
|
180 | |
$wrapper = pop if ref($_[-1]) eq 'CODE';
|
181 | |
my($name, $args, $ret, $proto) = @_;
|
182 | |
|
183 | |
my($symbol_name, $perl_name) = ref $name ? (@$name) : ($name, $name);
|
184 | |
my $function = _ffi_object->function($symbol_name, $args, $ret, $wrapper);
|
185 | |
$function->attach($perl_name, $proto);
|
186 | |
();
|
187 | |
}
|
188 | |
|
189 | |
=head2 closure
|
190 | |
|
191 | |
my $closure = closure $codeblock;
|
192 | |
|
193 | |
Create a closure that can be passed into a C function. For details on closures, see L<FFI::Platypus::Type#Closures>.
|
194 | |
|
195 | |
Example:
|
196 | |
|
197 | |
my $closure1 = closure { return $_[0] * 2 };
|
198 | |
my $closure2 = closure sub { return $_[0] * 4 };
|
199 | |
|
200 | |
=cut
|
201 | |
|
202 | |
sub closure (&)
|
203 | |
{
|
204 | |
my($coderef) = @_;
|
205 | |
require FFI::Platypus::Closure;
|
206 | |
FFI::Platypus::Closure->new($coderef);
|
207 | |
}
|
208 | |
|
209 | |
=head2 sticky
|
210 | |
|
211 | |
my $closure = sticky closure $codeblock;
|
212 | |
|
213 | |
Keyword to indicate the closure should not be deallocated for the life
|
214 | |
of the current process.
|
215 | |
|
216 | |
If you pass a closure into a C function without saving a reference to it
|
217 | |
like this:
|
218 | |
|
219 | |
foo(closure { ... }); # BAD
|
220 | |
|
221 | |
Perl will not see any references to it and try to free it immediately.
|
222 | |
(this has to do with the way Perl and C handle responsibilities for
|
223 | |
memory allocation differently). One fix for this is to make sure the
|
224 | |
closure remains in scope using either C<my> or C<our>. If you know the
|
225 | |
closure will need to remain in existence for the life of the process (or
|
226 | |
if you do not care about leaking memory), then you can add the sticky
|
227 | |
keyword to tell L<FFI::Platypus> to keep the thing in memory.
|
228 | |
|
229 | |
foo(sticky closure { ... }); # OKAY
|
230 | |
|
231 | |
=cut
|
232 | |
|
233 | |
sub sticky ($)
|
234 | |
{
|
235 | |
my($closure) = @_;
|
236 | |
Carp::croak("usage: sticky \$closure")
|
237 | |
unless defined $closure && ref($closure) eq 'FFI::Platypus::Closure';
|
238 | |
$closure->sticky;
|
239 | |
$closure;
|
240 | |
}
|
241 | |
|
242 | |
=head2 cast
|
243 | |
|
244 | |
my $converted_value = cast $original_type, $converted_type, $original_value;
|
245 | |
|
246 | |
The C<cast> function converts an existing I<$original_value> of type
|
247 | |
I<$original_type> into one of type I<$converted_type>. Not all types
|
248 | |
are supported, so care must be taken. For example, to get the address
|
249 | |
of a string, you can do this:
|
250 | |
|
251 | |
my $address = cast 'string' => 'opaque', $string_value;
|
252 | |
|
253 | |
=cut
|
254 | |
|
255 | |
sub cast ($$$)
|
256 | |
{
|
257 | |
_ffi_object->cast(@_);
|
258 | |
}
|
259 | |
|
260 | |
=head2 attach_cast
|
261 | |
|
262 | |
attach_cast "cast_name", $original_type, $converted_type;
|
263 | |
my $converted_value = cast_name($original_value);
|
264 | |
|
265 | |
This function creates a subroutine which can be used to convert
|
266 | |
variables just like the L<cast|FFI::Platypus::Declare#cast> function
|
267 | |
above. The above synopsis is roughly equivalent to this:
|
268 | |
|
269 | |
sub cast_name { cast($original_type, $converted_type, $_[0]) }
|
270 | |
my $converted_value = cast_name($original_value);
|
271 | |
|
272 | |
Except that the L<attach_cast|FFI::Platypus::Declare#attach_cast>
|
273 | |
variant will be much faster if called multiple times since the cast does
|
274 | |
not need to be dynamically allocated on each instance.
|
275 | |
|
276 | |
=cut
|
277 | |
|
278 | |
sub attach_cast ($$$)
|
279 | |
{
|
280 | |
my($name, $type1, $type2) = @_;
|
281 | |
my $caller = caller;
|
282 | |
$name = join '::', $caller, $name;
|
283 | |
_ffi_object->attach_cast($name, $type1, $type2);
|
284 | |
}
|
285 | |
|
286 | |
=head2 sizeof
|
287 | |
|
288 | |
my $size = sizeof $type;
|
289 | |
|
290 | |
Returns the total size of the given type. For example to get the size
|
291 | |
of an integer:
|
292 | |
|
293 | |
my $intsize = sizeof 'int'; # usually 4 or 8 depending on platform
|
294 | |
|
295 | |
You can also get the size of arrays
|
296 | |
|
297 | |
my $intarraysize = sizeof 'int[64]';
|
298 | |
|
299 | |
Keep in mind that "pointer" types will always be the pointer / word size
|
300 | |
for the platform that you are using. This includes strings, opaque and
|
301 | |
pointers to other types.
|
302 | |
|
303 | |
This function is not very fast, so you might want to save this value as
|
304 | |
a constant, particularly if you need the size in a loop with many
|
305 | |
iterations.
|
306 | |
|
307 | |
=cut
|
308 | |
|
309 | |
sub sizeof ($)
|
310 | |
{
|
311 | |
_ffi_object->sizeof($_[0]);
|
312 | |
}
|
313 | |
|
314 | |
=head2 lang
|
315 | |
|
316 | |
lang $language;
|
317 | |
|
318 | |
Specifies the foreign language that you will be interfacing with. The
|
319 | |
default is C. The foreign language specified with this attribute
|
320 | |
changes the default native types (for example, if you specify
|
321 | |
L<Rust|FFI::Platypus::Lang::Rust>, you will get C<i32> as an alias for
|
322 | |
C<sint32> instead of C<int> as you do with L<C|FFI::Platypus::Lang::C>).
|
323 | |
|
324 | |
In the future this may attribute may offer hints when doing demangling
|
325 | |
of languages that require it like L<C++|FFI::Platypus::Lang::CPP>.
|
326 | |
|
327 | |
=cut
|
328 | |
|
329 | |
sub lang ($)
|
330 | |
{
|
331 | |
_ffi_object->lang($_[0]);
|
332 | |
}
|
333 | |
|
334 | |
=head2 abi
|
335 | |
|
336 | |
abi $abi;
|
337 | |
|
338 | |
Set the ABI or calling convention for use in subsequent calls
|
339 | |
to L</attach>. May be either a string name or integer value
|
340 | |
from L<FFI::Platypus#abis>.
|
341 | |
|
342 | |
=cut
|
343 | |
|
344 | |
sub abi ($)
|
345 | |
{
|
346 | |
_ffi_object->abi($_[0]);
|
347 | |
}
|
348 | |
|
349 | |
sub import
|
350 | |
{
|
351 | |
my $caller = caller;
|
352 | |
shift; # class
|
353 | |
|
354 | |
foreach my $arg (@_)
|
355 | |
{
|
356 | |
if(ref $arg)
|
357 | |
{
|
358 | |
if($arg->[0] =~ /::/)
|
359 | |
{
|
360 | |
_ffi_object->load_custom_type(@$arg);
|
361 | |
no strict 'refs';
|
362 | |
*{join '::', $caller, $arg->[1]} = sub () { $arg->[1] };
|
363 | |
}
|
364 | |
else
|
365 | |
{
|
366 | |
_ffi_object->type(@$arg);
|
367 | |
no strict 'refs';
|
368 | |
*{join '::', $caller, $arg->[1]} = sub () { $arg->[0] };
|
369 | |
}
|
370 | |
}
|
371 | |
else
|
372 | |
{
|
373 | |
_ffi_object->type($arg);
|
374 | |
no strict 'refs';
|
375 | |
*{join '::', $caller, $arg} = sub () { $arg };
|
376 | |
}
|
377 | |
}
|
378 | |
|
379 | |
no strict 'refs';
|
380 | |
*{join '::', $caller, 'lib'} = \&lib;
|
381 | |
*{join '::', $caller, 'type'} = \&type;
|
382 | |
*{join '::', $caller, 'type_meta'} = \&type_meta;
|
383 | |
*{join '::', $caller, 'custom_type'} = \&custom_type;
|
384 | |
*{join '::', $caller, 'load_custom_type'} = \&load_custom_type;
|
385 | |
*{join '::', $caller, 'attach'} = \&attach;
|
386 | |
*{join '::', $caller, 'closure'} = \&closure;
|
387 | |
*{join '::', $caller, 'sticky'} = \&sticky;
|
388 | |
*{join '::', $caller, 'cast'} = \&cast;
|
389 | |
*{join '::', $caller, 'attach_cast'} = \&attach_cast;
|
390 | |
*{join '::', $caller, 'sizeof'} = \&sizeof;
|
391 | |
*{join '::', $caller, 'lang'} = \⟨
|
392 | |
*{join '::', $caller, 'abi'} = \&abi;
|
393 | |
}
|
394 | |
|
395 | |
1;
|
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 | |
=cut
|