1FFI::Platypus::Bundle(3U)ser Contributed Perl DocumentatiFoFnI::Platypus::Bundle(3)
2
3
4
6 FFI::Platypus::Bundle - Bundle foreign code with your Perl module
7
9 version 1.10
10
12 "ffi/foo.c":
13
14 #include <ffi_platypus_bundle.h>
15 #include <string.h>
16
17 typedef struct {
18 char *name;
19 int value;
20 } foo_t;
21
22 foo_t*
23 foo__new(const char *class_name, const char *name, int value)
24 {
25 (void)class_name;
26 foo_t *self = malloc( sizeof( foo_t ) );
27 self->name = strdup(name);
28 self->value = value;
29 return self;
30 }
31
32 const char *
33 foo__name(foo_t *self)
34 {
35 return self->name;
36 }
37
38 int
39 foo__value(foo_t *self)
40 {
41 return self->value;
42 }
43
44 void
45 foo__DESTROY(foo_t *self)
46 {
47 free(self->name);
48 free(self);
49 }
50
51 "lib/Foo.pm":
52
53 package Foo;
54
55 use strict;
56 use warnings;
57 use FFI::Platypus;
58
59 {
60 my $ffi = FFI::Platypus->new( api => 1 );
61
62 $ffi->type('object(Foo)' => 'foo_t');
63 $ffi->mangler(sub {
64 my $name = shift;
65 $name =~ s/^/foo__/;
66 $name;
67 });
68
69 $ffi->bundle;
70
71 $ffi->attach( new => [ 'string', 'string', 'int' ] => 'foo_t' );
72 $ffi->attach( name => [ 'foo_t' ] => 'string' );
73 $ffi->attach( value => [ 'foo_t' ] => 'int' );
74 $ffi->attach( DESTROY => [ 'foo_t' ] => 'void' );
75 }
76
77 1;
78
79 "t/foo.t"
80
81 use Test::More;
82 use Foo;
83
84 my $foo = Foo->new("platypus", 10);
85 isa_ok $foo, 'Foo';
86 is $foo->name, "platypus";
87 is $foo->value, 10;
88
89 done_testing;
90
91 "Makefile.PL":
92
93 use ExtUtils::MakeMaker;
94 use FFI::Build::MM;
95 my $fbmm = FFI::Build::MM->new;
96 WriteMakefile(
97 $fbmm->mm_args(
98 NAME => 'Foo',
99 DISTNAME => 'Foo',
100 VERSION => '1.00',
101 # ...
102 )
103 );
104
105 sub MY::postamble
106 {
107 $fbmm->mm_postamble;
108 }
109
110 or "dist.ini":
111
112 name = Foo
113 version = 0.01
114 ...
115
116 [FFI::Build]
117 version = 1.04
118
120 This document serves as a tutorial for using the new bundling interface
121 provided by FFI::Platypus as of api version 1. It requires
122 FFI::Platypus of at least 1.00.
123
124 Sometimes when writing FFI bindings you need to include a little C code
125 (or your favorite compiled language) to finish things off.
126 Alternatively, you might just want to write some C code (or your
127 favorite compiled language) to include with your Perl module to make a
128 tight loop faster. The bundling interface has you covered.
129
130 Basic example
131 To illustrate we will go through the files in the synopsis and explain
132 how and why they work. To start with we have some C code which
133 emulates object oriented code using "foo__" as a prefix. We use a C
134 struct that we call "foo_t" to store our object data. On the C level
135 the struct acts as a class, when combined with its functions that act
136 as methods. The constructor just allocates the memory it needs for the
137 "foo_t" instance, fills in the appropriate fields and returns the
138 pointer:
139
140 foo_t*
141 foo__new(const char *class_name, const char *name, int value)
142 {
143 (void) class_name;
144 foo_t *self = malloc( sizeof( foo_t ) );
145 self->name = strdup(name);
146 self->value = value;
147 return self;
148 }
149
150 We include a class name as the first argument, because Perl will
151 include that when calling the constructor, but we do not use it here.
152 An exercise for the reader would be to add hierarchical inheritance.
153
154 There are also some methods which return member values. This class has
155 only read only members, but you could have read/write or other methods
156 depending on your needs.
157
158 const char *
159 foo__name(foo_t *self)
160 {
161 return self->name;
162 }
163
164 We also include a destructor so that the memory owned by the object can
165 be freed when it is no longer needed.
166
167 void
168 foo__DESTROY(foo_t *self)
169 {
170 free(self->name);
171 free(self);
172 }
173
174 This might start to look a little like a Perl module, and when we look
175 at the Perl code that binds to this code, you will see why. First lets
176 prepare the FFI::Platypus instance and specify the correct api version:
177
178 my $ffi = FFI::Platypus->new( api => 1 );
179
180 The bundle interface is only supported with api version 1, so if you
181 try to use version 0 it will not work. Next we define an object type
182 for "foo_t" which will associate it with the Perl class "Foo".
183
184 $ffi->type('object(Foo)' => 'foo_t');
185
186 As object type is a blessed reference to an opaque (default) or integer
187 type which can be used as a Perl object. Platypus does the translating
188 of Perl object to and from the foo_t pointers that the C code
189 understands. For more details on Platypus types see
190 FFI::Platypus::Type.
191
192 Next we set the mangler on the Platypus instance so that we can refer
193 to function names without the "foo__" prefix. You could just not use
194 the prefix in your C code and skip this step, or you could refer to the
195 function names in their full in your Perl code, however, this saves
196 extra typing and allows you to bundle more than one class with your
197 Perl code without having to worry about name conflicts.
198
199 $ffi->mangler(sub {
200 my $name = shift;
201 $name =~ s/^/foo__/;
202 $name;
203 });
204
205 Finally we let Platypus know that we will be bundling code.
206
207 $ffi->bundle;
208
209 By default, this searches for the appropriate place for your dynamic
210 libraries using the current package. In some cases you may need to
211 override this, for example if your dist is named "Foo-Bar" but your
212 specific class is named "Foo::Bar::Baz", you'd want something like
213 this:
214
215 package Foo::Bar::Baz;
216 use FFI::Platypus;
217 my $ffi = FFI::Platypus->new( api => 1 );
218 $ffi->bundle('Foo::Bar');
219 ...
220
221 Now, finally we can attach the methods for our class:
222
223 $ffi->attach( new => [ 'string', 'int' ] => 'foo_t' );
224 $ffi->attach( name => [ 'foo_t' ] => 'string' );
225 $ffi->attach( value => [ 'foo_t' ] => 'int' );
226 $ffi->attach( DESTROY => [ 'foo_t' ] => 'void' );
227
228 Note that we do not have to include the "foo__" prefix because of the
229 way we set up the mangler. If we hadn't done that then we could
230 instead attach with the full names:
231
232 $ffi->attach( [ 'foo__new' => 'new' ] => [ 'string', 'int' ] => 'foo_t' );
233 $ffi->attach( [ 'foo__name' => 'name' ] => [ 'foo_t' ] => 'string' );
234 ...
235
236 You're done! You can now use this class. Lets write a test to make
237 sure it works,
238
239 use strict;
240 use warnings;
241 use Test::More;
242 use Foo;
243
244 my $foo = Foo->new("platypus", 10);
245 isa_ok $foo, 'Foo';
246 is $foo->name, "platypus";
247 is $foo->value, 10;
248
249 done_testing;
250
251 and use "prove" to check that it works:
252
253 % prove -lvm
254 t/foo.t ..
255 ok 1 - An object of class 'Foo' isa 'Foo'
256 ok 2
257 ok 3
258 1..3
259 ok
260 All tests successful.
261 Files=1, Tests=3, 0 wallclock secs ( 0.02 usr 0.00 sys + 0.14 cusr 0.03 csys = 0.19 CPU)
262 Result: PASS
263
264 Platypus automatically compiles and links the dynamic library for you:
265
266 % ls ffi/_build
267 foo.c.o libFoo.so
268
269 The C code will be rebuilt next time if the source code is newer than
270 the object or dynamic libraries files. If the source files are not
271 changed, then it won't be rebuilt to save time. If you are using the
272 code without MakeMaker, or another build system you are responsible for
273 cleaning up these files. This is intended as a convenience to allow
274 you to test your code without having to invoke MakeMaker, or "dzil" or
275 whatever build system you are using.
276
277 When you distribute your module though, you will want the dynamic
278 library built just once at build-time and installed correctly so that
279 it can be found at run-time. You don't need to make any changes to
280 your C or Perl code, but you do need to tell MakeMaker to build and
281 install the appropriate files using FFI::Build::MM:
282
283 use ExtUtils::MakeMaker;
284 use FFI::Build::MM;
285 my $fbmm = FFI::Build::MM->new;
286 WriteMakefile(
287 $fbmm->mm_args(
288 NAME => 'Foo',
289 DISTNAME => 'Foo',
290 VERSION => '1.00',
291 # ...
292 )
293 );
294
295 sub MY::postamble
296 {
297 $fbmm->mm_postamble;
298 }
299
300 And we can invoke all the normal MakeMaker style stuff and our C code
301 will be compiled, linked and installed at the appropriate steps.
302
303 % perl Makefile.PL
304 Generating a Unix-style Makefile
305 Writing Makefile for Foo
306 Writing MYMETA.yml and MYMETA.json
307 % make
308 cp lib/Foo.pm blib/lib/Foo.pm
309 "/Users/ollisg/perl5/perlbrew/perls/perl-5.30.0/bin/perl" -MFFI::Build::MM=cmd -e fbx_build
310 CC ffi/foo.c
311 LD blib/lib/auto/share/dist/Foo/lib/libFoo.dylib
312 % make test
313 "/Users/ollisg/perl5/perlbrew/perls/perl-5.30.0/bin/perl" -MFFI::Build::MM=cmd -e fbx_build
314 "/Users/ollisg/perl5/perlbrew/perls/perl-5.30.0/bin/perl" -MFFI::Build::MM=cmd -e fbx_test
315 PERL_DL_NONLAZY=1 "/Users/ollisg/perl5/perlbrew/perls/perl-5.30.0/bin/perl" "-MExtUtils::Command::MM" "-MTest::Harness" "-e" "undef *Test::Harness::Switches; test_harness(0, 'blib/lib', 'blib/arch')" t/*.t
316 t/foo.t .. ok
317 All tests successful.
318 Files=1, Tests=3, 0 wallclock secs ( 0.01 usr 0.00 sys + 0.06 cusr 0.01 csys = 0.08 CPU)
319 Result: PASS
320
321 If the "Makefile.PL" file above looks overly complicated, you can use
322 the Dist::Zilla::Plugin::FFI::Build plugin to simplify your life if you
323 are using Dist::Zilla:
324
325 [FFI::Build]
326 version = 1.04
327
328 Specifying version 1.04 will ensure that any ".o" or ".so" files are
329 pruned from your build tree and not distributed by mistake.
330
331 Initialization example
332 The bundle interface also gives you entry points which will be called
333 automatically when your code is loaded and unloaded if they are found.
334
335 "ffi_pl_bundle_init"
336 void ffi_pl_bundle_init(const char *package, int argc, void *argv[]);
337
338 Called when the dynamic library is loaded. "package" is the Perl
339 package that called "bundle" from Perl space. "argc" and "argv"
340 represents an array of opaque pointers that can be passed as an
341 array to bundle as the last argument. (the count "argc" is a
342 little redundant because "argv" is also NULL terminated).
343
344 "ffi_pl_bundle_constant"
345 void ffi_pl_bundle_constant(const char *package, ffi_platypus_constant_t *c);
346
347 Called immediately after "ffi_pl_bundle_init", and is intended to
348 allow you to set Perl constants from C space. For details on how
349 this works and what methods you can call on the
350 "ffi_platypus_constant_t" instance, see FFI::Platypus::Constant.
351
352 "ffi_pl_bundle_fini"
353 void ffi_pl_bundle_fini(const char *package);
354
355 Called when the dynamic library is unloaded. "package" is the Perl
356 package that called "bundle" from Perl space when the library was
357 loaded. CAVEAT: if you attach any functions then this will never
358 be called, because attaching functions locks the Platypus instance
359 into memory along with the libraries which it is using.
360
361 Here is an example that passes the version and a callback back into
362 Perl space that emulates the Perl 5.10 "say" feature.
363
364 "ffi/init.c":
365
366 #include <ffi_platypus_bundle.h>
367
368 char buffer[512];
369 const char *version;
370 void (*say)(const char *);
371
372 void
373 ffi_pl_bundle_init(const char *package, int argc, void *argv[])
374 {
375 version = argv[0];
376 say = argv[1];
377
378 say("in init!");
379
380 snprintf(buffer, 512, "package = %s, version = %s", package, version);
381 say(buffer);
382
383 snprintf(buffer, 512, "args = %d", argc);
384 say(buffer);
385 }
386
387 void
388 ffi_pl_bundle_fini(const char *package)
389 {
390 say("in fini!");
391 }
392
393 "lib/Init.pm":
394
395 package Init;
396
397 use strict;
398 use warnings;
399 use FFI::Platypus;
400
401 our $VERSION = '1.00';
402
403 {
404 my $ffi = FFI::Platypus->new( api => 1 );
405
406 my $say = $ffi->closure(sub {
407 my $string = shift;
408 print "$string\n";
409 });
410
411 $ffi->bundle([
412 $ffi->cast( 'string' => 'opaque', $VERSION ),
413 $ffi->cast( '(string)->void' => 'opaque', $say ),
414 ]);
415
416 undef $ffi;
417 undef $say;
418 }
419
420 1;
421
422 The deinitialization order for the $say callback and the $ffi instance
423 is essential here, so we do it manually with "undef":
424
425 undef $ffi;
426 undef $say;
427
428 First we deallocate $ffi which calls "ffi_pl_bundle_fini", which calls
429 $say, so we want to make sure the latter is still allocated. Once
430 "ffi_pl_bundle_fini" is done, we can safely deallocate $say.
431
432 If "ffi_pl_bundle_fini" didn't call back into Perl space like this then
433 we don't have to be as careful about deallocating things in Perl space.
434
436 Author: Graham Ollis <plicease@cpan.org>
437
438 Contributors:
439
440 Bakkiaraj Murugesan (bakkiaraj)
441
442 Dylan Cali (calid)
443
444 pipcet
445
446 Zaki Mughal (zmughal)
447
448 Fitz Elliott (felliott)
449
450 Vickenty Fesunov (vyf)
451
452 Gregor Herrmann (gregoa)
453
454 Shlomi Fish (shlomif)
455
456 Damyan Ivanov
457
458 Ilya Pavlov (Ilya33)
459
460 Petr Pisar (ppisar)
461
462 Mohammad S Anwar (MANWAR)
463
464 Håkon Hægland (hakonhagland, HAKONH)
465
466 Meredith (merrilymeredith, MHOWARD)
467
468 Diab Jerius (DJERIUS)
469
471 This software is copyright (c) 2015,2016,2017,2018,2019 by Graham
472 Ollis.
473
474 This is free software; you can redistribute it and/or modify it under
475 the same terms as the Perl 5 programming language system itself.
476
477
478
479perl v5.30.1 2020-02-06 FFI::Platypus::Bundle(3)