This file is indexed.

/usr/lib/x86_64-linux-gnu/perl5/5.24/FFI/Platypus/Type.pod is in libffi-platypus-perl 0.45-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

   1
   2
   3
   4
   5
   6
   7
   8
   9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  36
  37
  38
  39
  40
  41
  42
  43
  44
  45
  46
  47
  48
  49
  50
  51
  52
  53
  54
  55
  56
  57
  58
  59
  60
  61
  62
  63
  64
  65
  66
  67
  68
  69
  70
  71
  72
  73
  74
  75
  76
  77
  78
  79
  80
  81
  82
  83
  84
  85
  86
  87
  88
  89
  90
  91
  92
  93
  94
  95
  96
  97
  98
  99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326
 327
 328
 329
 330
 331
 332
 333
 334
 335
 336
 337
 338
 339
 340
 341
 342
 343
 344
 345
 346
 347
 348
 349
 350
 351
 352
 353
 354
 355
 356
 357
 358
 359
 360
 361
 362
 363
 364
 365
 366
 367
 368
 369
 370
 371
 372
 373
 374
 375
 376
 377
 378
 379
 380
 381
 382
 383
 384
 385
 386
 387
 388
 389
 390
 391
 392
 393
 394
 395
 396
 397
 398
 399
 400
 401
 402
 403
 404
 405
 406
 407
 408
 409
 410
 411
 412
 413
 414
 415
 416
 417
 418
 419
 420
 421
 422
 423
 424
 425
 426
 427
 428
 429
 430
 431
 432
 433
 434
 435
 436
 437
 438
 439
 440
 441
 442
 443
 444
 445
 446
 447
 448
 449
 450
 451
 452
 453
 454
 455
 456
 457
 458
 459
 460
 461
 462
 463
 464
 465
 466
 467
 468
 469
 470
 471
 472
 473
 474
 475
 476
 477
 478
 479
 480
 481
 482
 483
 484
 485
 486
 487
 488
 489
 490
 491
 492
 493
 494
 495
 496
 497
 498
 499
 500
 501
 502
 503
 504
 505
 506
 507
 508
 509
 510
 511
 512
 513
 514
 515
 516
 517
 518
 519
 520
 521
 522
 523
 524
 525
 526
 527
 528
 529
 530
 531
 532
 533
 534
 535
 536
 537
 538
 539
 540
 541
 542
 543
 544
 545
 546
 547
 548
 549
 550
 551
 552
 553
 554
 555
 556
 557
 558
 559
 560
 561
 562
 563
 564
 565
 566
 567
 568
 569
 570
 571
 572
 573
 574
 575
 576
 577
 578
 579
 580
 581
 582
 583
 584
 585
 586
 587
 588
 589
 590
 591
 592
 593
 594
 595
 596
 597
 598
 599
 600
 601
 602
 603
 604
 605
 606
 607
 608
 609
 610
 611
 612
 613
 614
 615
 616
 617
 618
 619
 620
 621
 622
 623
 624
 625
 626
 627
 628
 629
 630
 631
 632
 633
 634
 635
 636
 637
 638
 639
 640
 641
 642
 643
 644
 645
 646
 647
 648
 649
 650
 651
 652
 653
 654
 655
 656
 657
 658
 659
 660
 661
 662
 663
 664
 665
 666
 667
 668
 669
 670
 671
 672
 673
 674
 675
 676
 677
 678
 679
 680
 681
 682
 683
 684
 685
 686
 687
 688
 689
 690
 691
 692
 693
 694
 695
 696
 697
 698
 699
 700
 701
 702
 703
 704
 705
 706
 707
 708
 709
 710
 711
 712
 713
 714
 715
 716
 717
 718
 719
 720
 721
 722
 723
 724
 725
 726
 727
 728
 729
 730
 731
 732
 733
 734
 735
 736
 737
 738
 739
 740
 741
 742
 743
 744
 745
 746
 747
 748
 749
 750
 751
 752
 753
 754
 755
 756
 757
 758
 759
 760
 761
 762
 763
 764
 765
 766
 767
 768
 769
 770
 771
 772
 773
 774
 775
 776
 777
 778
 779
 780
 781
 782
 783
 784
 785
 786
 787
 788
 789
 790
 791
 792
 793
 794
 795
 796
 797
 798
 799
 800
 801
 802
 803
 804
 805
 806
 807
 808
 809
 810
 811
 812
 813
 814
 815
 816
 817
 818
 819
 820
 821
 822
 823
 824
 825
 826
 827
 828
 829
 830
 831
 832
 833
 834
 835
 836
 837
 838
 839
 840
 841
 842
 843
 844
 845
 846
 847
 848
 849
 850
 851
 852
 853
 854
 855
 856
 857
 858
 859
 860
 861
 862
 863
 864
 865
 866
 867
 868
 869
 870
 871
 872
 873
 874
 875
 876
 877
 878
 879
 880
 881
 882
 883
 884
 885
 886
 887
 888
 889
 890
 891
 892
 893
 894
 895
 896
 897
 898
 899
 900
 901
 902
 903
 904
 905
 906
 907
 908
 909
 910
 911
 912
 913
 914
 915
 916
 917
 918
 919
 920
 921
 922
 923
 924
 925
 926
 927
 928
 929
 930
 931
 932
 933
 934
 935
 936
 937
 938
 939
 940
 941
 942
 943
 944
 945
 946
 947
 948
 949
 950
 951
 952
 953
 954
 955
 956
 957
 958
 959
 960
 961
 962
 963
 964
 965
 966
 967
 968
 969
 970
 971
 972
 973
 974
 975
 976
 977
 978
 979
 980
 981
 982
 983
 984
 985
 986
 987
 988
 989
 990
 991
 992
 993
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
# PODNAME: FFI::Platypus::Type
# ABSTRACT: Defining types for FFI::Platypus
# VERSION

__END__

=pod

=encoding UTF-8

=head1 NAME

FFI::Platypus::Type - Defining types for FFI::Platypus

=head1 VERSION

version 0.45

=head1 SYNOPSIS

OO Interface:

 use FFI::Platypus;
 my $ffi = FFI::Platypus->new;
 $ffi->type('int' => 'my_int');

=head1 DESCRIPTION

This document describes how to define types using L<FFI::Platypus>.  
Types may be "defined" ahead of time, or simply used when defining or 
attaching functions.

 # OO example of defining types
 use FFI::Platypus;
 my $ffi = FFI::Platypus->new;
 $ffi->type('int');
 $ffi->type('string');
 
 # OO example of simply using types in function declaration or attachment
 my $f = $ffi->function(puts => ['string'] => 'int');
 $ffi->attach(puts => ['string'] => 'int');

If you are using the declarative interface, you can either pass the 
types you need to the L<FFI::Platypus::Declare> C<use> invocation, or 
you can use the L<FFI::Platypus::Declare#type> function.  The advantage 
of the former is that it creates a Perl constant for that type so that 
you do not need to use quotation marks when using the type.

 # Declarative with use
 use FFI::Platypus::Declare 'string', 'int';
 attach puts => [string] => int;

 # Declarative with type
 use FFI::Platypus::Declare;
 type 'string';
 type 'int';
 attach puts => ['string'] => 'int';

Unless you are using aliases the L<FFI::Platypus#type> method or
L<FFI::Platypus::Declare#type> function are not necessary, but they
will throw an exception if the type is incorrectly specified or not
supported, which may be helpful.

Note: This document sometimes uses the term "C Function" as short hand 
for function implemented in a compiled language.  Unless the term is 
referring literally to a C function example code, you can assume that 
it should also work with another compiled language.

=head2 meta information about types

You can get the size of a type using the L<FFI::Platypus#sizeof> method.

 # OO interface
 my $intsize = $ffi->sizeof('int');
 my intarraysize = $ffi->sizeof('int[64]');
 
 # Declare interface
 my $intsize = sizeof 'int';
 my intarraysize = sizeof 'int[64]';

=head2 converting types

Sometimes it is necessary to convert types.  In particular various 
pointer types often need to be converted for consumption in Perl.  For 
this purpose the L<FFI::Platypus#cast> method is provided.  It needs to 
be used with care though, because not all type combinations are 
supported.  Here are some useful ones:

 # OO interface
 my $address = $ffi->cast('string' => 'opaque', $string);
 my $string  = $ffi->cast('opaque' => 'string', $pointer);
 
 # Declare interface
 use FFI::Platypus::Declare;
 my $address = cast 'string' => 'opaque', $string;
 my $string  = cast 'opaque' => 'string', $pointer;

=head2 aliases

Some times using alternate names is useful for documenting the purpose 
of an argument or return type.  For this "aliases" can be helpful.  The 
second argument to the L<FFI::Platypus#type> method or 
L<FFI::Platypus::Declare#type> function can be used to define a type 
alias that can later be used by function declaration and attachment.

 # OO style
 use FFI::Platypus;
 my $ffi = FFI::Platypus->new;
 $ffi->type('int'    => 'myint');
 $ffi->type('string' => 'mystring');
 my $f = $ffi->function( puts => ['mystring'] => 'myint' );
 $ffi->attach( puts => ['mystring'] => 'myint' );

 # Declarative style
 use FFI::Platypus::Declare;
 type 'int'    => 'myint';
 type 'string' => 'mystring';
 attach puts => ['mystring'] => 'myint';

 # Declarative style with use (and with fewer quotes)
 use FFI::Platypus::Declare
   [ int    => 'myint' ],
   [ string => 'mystring' ];
 attach puts => [mystring] => myint;

Aliases are contained without the L<FFI::Platypus> object, or the 
current package if you are using L<FFI::Platypus::Declare>, so feel free 
to define your own crazy types without stepping on the toes of other 
CPAN Platypus developers.

=for stopwords tm

=head1 TYPE CATEGORIES

=head2 Native types

So called native types are the types that the CPU understands that can 
be passed on the argument stack or returned by a function.  It does not 
include more complicated types like arrays or structs, which can be 
passed via pointers (see the opaque type below).  Generally native types 
include void, integers, floats and pointers.

=head3 the void type

This can be used as a return value to indicate a function does not 
return a value (or if you want the return value to be ignored).

=head3 integer types

The following native integer types are always available (parentheticals 
indicates the usual corresponding C type):

=over 4

=item sint8

Signed 8 bit byte (C<signed char>, C<int8_t>).

=item uint8

Unsigned 8 bit byte (C<unsigned char>, C<uint8_t>).

=item sint16

Signed 16 bit integer (C<short>, C<int16_t>)

=item uint16

Unsigned 16 bit integer (C<unsigned short>, C<uint16_t>)

=item sint32

Signed 32 bit integer (C<int>, C<int32_t>)

=item uint32

Unsigned 32 bit integer (C<unsigned int>, C<uint32_t>)

=item sint64

Signed 64 bit integer (C<long> or C<long long>, C<int64_t>)

=item uint64

Unsigned 64 bit integer (C<unsigned long> or C<unsigned long long>, 
C<uint64_t>)

=back

You may also use C<uchar>, C<ushort>, C<uint> and C<ulong> as short
names for C<unsigned char>, C<unsigned short>, C<unsigned int> and
C<unsigned long>.

These integer types are also available, but there actual size and sign 
may depend on the platform.

=over 4

=item char

Somewhat confusingly, C<char> is an integer type!  This is really an 
alias for either C<sint8_t> or C<uint8_t> depending on your platform.  
If you want to pass a character (not integer) in to a C function that 
takes a character you want to use the perl L<ord|perlfunc#ord> function. 
Here is an example that uses the standard libc C<isalpha>, C<isdigit> 
type functions:

 use FFI::Platypus;
 
 my $ffi = FFI::Platypus->new;
 $ffi->lib(undef);
 $ffi->type('int' => 'character');
 
 my @list = qw( 
   alnum alpha ascii blank cntrl digit lower print punct 
   space upper xdigit
 );
 
 $ffi->attach("is$_" => ['character'] => 'int') for @list;
 
 my $char = shift(@ARGV) || 'a';
 
 no strict 'refs';
 printf "'%s' is %s %s\n", $char, $_, &{'is'.$_}(ord $char) for @list;

=item size_t

This is usually an C<unsigned long>, but it is up to the compiler to 
decide.  The C<malloc> function is defined in terms of C<size_t>:

 use FFI::Platypus::Declare qw( size_t opaque );
 attach malloc => [size_t] => opaque;

(Note that you can get C<malloc> from L<FFI::Platypus::Memory>).

=back

There are a number of other types that may or may not be available if 
they are detected when L<FFI::Platypus> is installed.  This includes 
things like C<wchar_t>, C<off_t>, C<wint_t>. You can use this script to 
list all the integer types that L<FFI::Platypus> knows about, plus how 
they are implemented.

 use FFI::Platypus;
 
 my $ffi = FFI::Platypus->new;
 
 foreach my $type_name (sort FFI::Platypus->types)
 {
   my $meta = $ffi->type_meta($type_name);
   next unless $meta->{element_type} eq 'int';
   printf "%20s %s\n", $type_name, $meta->{ffi_type};
 }

If you need a common system type that is not provided, please open a 
ticket in the Platypus project's GitHub issue tracker.  Be sure to 
include the usual header file the type can be found in.

=head3 floating point types

The following native floating point types are always available 
(parentheticals indicates the usual corresponding C type):

=over 4

=item float

Single precision floating point (I<float>)

=item double

Double precision floating point (I<double>)

=item longdouble

Floating point that may be larger than C<double> (I<longdouble>).  This 
type is only available if supported by the C compiler used to build 
L<FFI::Platypus>.  There may be a performance penalty for using this 
type, even if your Perl uses long doubles internally for its number 
value (NV) type, because of the way L<FFI::Platypus> interacts with 
C<libffi>.

As an argument type either regular number values (NV) or instances of 
L<Math::LongDouble> are accepted.  When used as a return type, 
L<Math::LongDouble> will be used, if you have that module installed.  
Otherwise the return type will be downgraded to whatever your Perl's 
number value (NV) is.

=item complex_float

Complex single precision floating point (I<float complex>)

=item complex_double

Complex double precision floating point (I<double complex>)

C<complex_float> and C<complex_double> are only available if supported 
by your C compiler and by libffi.  Complex numbers are only supported in 
very recent versions of libffi, and as of this writing the latest 
production version doesn't work on x86_64.  It does seem to work with 
the latest production version of libffi on 32 bit Intel (x86), and with 
the latest libffi version in git on x86_64.

=back

Support for C<complex_float>, C<complex_double> and C<longdouble> are 
limited at the moment.  Complex types can only be used as simple 
arguments (not return types, pointers, arrays or record members) and the 
C<longdouble> can only be used as simple argument or return values (not 
pointers, arrays or record members).  Adding support for these is not 
difficult, but time consuming, so if you are in need of these features 
please do not hesitate to open a support ticket on the project's github 
issue tracker:

L<https://github.com/plicease/FFI-Platypus/issues>

In particular I am hesitant to implementing complex return types, as 
there are performance and interface ramifications, and I would 
appreciate talking to someone who is actually going to use these 
features.

=head3 opaque pointers

Opaque pointers are simply a pointer to a region of memory that you do 
not manage, and do not know the structure of. It is like a C<void *> in 
C.  These types are represented in Perl space as integers and get 
converted to and from pointers by L<FFI::Platypus>.  You may use 
C<pointer> as an alias for C<opaque>.  (The Platypus documentation uses 
the convention of using "pointer" to refer to pointers to known types 
(see below) and "opaque" as short hand for opaque pointer).

As an example, libarchive defines C<struct archive> type in its header 
files, but does not define its content.  Internally it is defined as a 
C<struct> type, but the caller does not see this.  It is therefore 
opaque to its caller.  There are C<archive_read_new> and 
C<archive_write_new> functions to create a new instance of this opaque 
object and C<archive_read_free> and C<archive_write_free> to destroy 
this objects when you are done.

 use FFI::Platypus::Declare qw( opaque int );
 attach archive_read_new   => []       => opaque;
 attach archive_write_new  => []       => opaque;
 attach archive_read_free  => [opaque] => int;
 attach archive_write_free => [opaque] => int;

As a special case, when you pass C<undef> into a function that takes an 
opaque type it will be translated into C<NULL> for C.  When a C function 
returns a NULL pointer, it will be translated back to C<undef>.

=head2 Strings

From the CPU's perspective, strings are just pointers.  From Perl and 
C's perspective, those pointers point to a series of characters.  For C 
they are null terminates ("\0").  L<FFI::Platypus> handles the details 
where they differ.  Basically when you see C<char *> or C<const char *> 
used in a C header file you can expect to be able to use the C<string> 
type.

 use FFI::Platypus::Declare qw( string int );
 attach puts => [string] => int;

Currently strings are only supported as simple argument and return types
and as argument (but not return types) for closures.  In the future pointers
to strings or arrays of strings may be supported.

=head2 Pointer / References

In C you can pass a pointer to a variable to a function in order 
accomplish the task of pass by reference.  In Perl the same is task is 
accomplished by passing a reference (although you can also modify the 
argument stack thus Perl supports proper pass by reference as well).

With L<FFI::Platypus> you can define a pointer types to any of the 
native types described above (that is all the types we have covered so 
far except for strings).  When using this you must make sure to pass in 
a reference to a scalar, or C<undef> (C<undef> will be translated into 
C<NULL>).

If the C code makes a change to the value pointed to by the pointer, the 
scalar will be updated before returning to Perl space.  Example, with C 
code.

 /* foo.c */
 void increment_int(int *value)
 {
   if(value != NULL)
     (*value)++;
   else
     fprintf(stderr, "NULL pointer!\n");
 }

 # foo.pl
 use FFI::Platypus::Declare 'void', ['int*' =>'int_p'];
 lib 'libfoo.so'; # change to reflect the dynamic lib 
                  # that contains foo.c
 attach increment_int => [int_p] => void;
 my $i = 0;
 increment_int(\$i);   # $i == 1
 increment_int(\$i);   # $i == 2
 increment_int(\$i);   # $i == 3
 increment_int(undef); # prints "NULL pointer!\n"

=head2 Records

Records are structured data of a fixed length.  In C they are called 
C<struct>s To declare a record type, use C<record>:

 $ffi->type( 'record (42)' => 'my_record_of_size_42_bytes' );

The easiest way to mange records with Platypus is by using 
L<FFI::Platypus::Record> to define a record layout for a record class. 
Here is a brief example:

 package My::UnixTime;
 
 use FFI::Platypus::Record;
 
 record_layout(qw(
     int    tm_sec
     int    tm_min
     int    tm_hour
     int    tm_mday
     int    tm_mon
     int    tm_year
     int    tm_wday
     int    tm_yday
     int    tm_isdst
     long   tm_gmtoff
     string tm_zone
 ));
 
 my $ffi = FFI::Platypus->new;
 $ffi->lib(undef);
 # define a record class My::UnixTime and alias it to "tm"
 $ffi->type("record(My::UnixTime)" => 'tm');
 
 # attach the C localtime function as a constructor
 $ffi->attach( localtime => ['time_t*'] => 'tm', sub {
   my($inner, $class, $time) = @_;
   $time = time unless defined $time;
   $inner->(\$time);
 });
 
 package main;
 
 # now we can actually use our My::UnixTime class
 my $time = My::UnixTime->localtime;
 printf "time is %d:%d:%d %s\n",
   $time->tm_hour,
   $time->tm_min,
   $time->tm_sec,
   $time->tm_zone;

For more detailed usage, see L<FFI::Platypus::Record>.

Platypus does not manage the structure of a record (that is up to you), 
it just keeps track of their size and makes sure that they are copied 
correctly when used as a return type.  A record in Perl is just a string 
of bytes stored as a scalar.  In addition to defining a record layout 
for a record class, there are a number of tools you can use manipulate 
records in Perl, two notable examples are L<pack and unpack|perlpacktut> 
and L<Convert::Binary::C>.

Here is an example with commentary that uses L<Convert::Binary::C> to 
extract the component time values from the C C<localtime> function, and 
then smushes them back together to get the original C<time_t> (an 
integer).

 use Convert::Binary::C;
 use FFI::Platypus;
 use Data::Dumper qw( Dumper );
 
 my $c = Convert::Binary::C->new;
 
 # Alignment of zero (0) means use
 # the alignment of your CPU
 $c->configure( Alignment => 0 );
 
 # parse the tm record structure so
 # that Convert::Binary::C knows
 # what to spit out and suck in
 $c->parse(<<ENDC);
 struct tm {
   int tm_sec;
   int tm_min;
   int tm_hour;
   int tm_mday;
   int tm_mon;
   int tm_year;
   int tm_wday;
   int tm_yday;
   int tm_isdst;
   long int tm_gmtoff;
   const char *tm_zone;
 };
 ENDC
 
 # get the size of tm so that we can give it
 # to Platypus
 my $tm_size = $c->sizeof("tm");
 
 # create the Platypus instance and create the appropriate
 # types and functions
 my $ffi = FFI::Platypus->new;
 $ffi->lib(undef);
 $ffi->type("record($tm_size)" => 'tm');
 $ffi->attach( [ localtime => 'my_localtime' ] => ['time_t*'] => 'tm'     );
 $ffi->attach( [ time      => 'my_time'      ] => ['tm']      => 'time_t' );
 
 # ===============================================
 # get the tm struct from the C localtime function
 # note that we pass in a reference to the value that time
 # returns because localtime takes a pointer to time_t
 # for some reason.
 my $time_hashref = $c->unpack( tm => my_localtime(\time) );
 
 # tm_zone comes back from Convert::Binary::C as an opaque,
 # cast it into a string.  We localize it to just this do
 # block so that it will be a pointer when we pass it back
 # to C land below.
 do {
   local $time_hashref->{tm_zone} = $ffi->cast(opaque => string => $time_hashref->{tm_zone});
   print Dumper($time_hashref);
 };
 
 # ===============================================
 # convert the tm struct back into an epoch value
 my $time = my_time( $c->pack( tm => $time_hashref ) );
 
 print "time      = $time\n";
 print "perl time = ", time, "\n";

You can also link a record type to a class.  It will then be accepted 
when blessed into that class as an argument passed into a C function, 
and when it is returned from a C function it will be blessed into that 
class.  Basically:

 $ffi->type( 'record(My::Class)' => 'my_class' );
 $ffi->attach( my_function1 => [ 'my_class' ] => 'void' );
 $ffi->attach( my_function2 => [ ] => 'my_class' );

The only thing that your class MUST provide is either a 
C<ffi_record_size> or C<_ffi_record_size> class method that returns the 
size of the record in bytes.

Here is a longer practical example, once again using the tm struct:

 package My::UnixTime;
 
 use FFI::Platypus;
 use FFI::TinyCC;
 use FFI::TinyCC::Inline 'tcc_eval';
 
 # store the source of the tm struct
 # for repeated use later
 my $tm_source = <<ENDTM;
   struct tm {
     int tm_sec;
     int tm_min;
     int tm_hour;
     int tm_mday;
     int tm_mon;
     int tm_year;
     int tm_wday;
     int tm_yday;
     int tm_isdst;
     long int tm_gmtoff;
     const char *tm_zone;
   };
 ENDTM
 
 # calculate the size of the tm struct
 # this time using Tiny CC
 my $tm_size = tcc_eval qq{
   $tm_source
   int main()
   {
     return sizeof(struct tm);
   }
 };
 
 # To use My::UnixTime as a record class, we need to
 # specify a size for the record, a function called
 # either ffi_record_size or _ffi_record_size should
 # return the size in bytes.  This function has to
 # be defined before you try to define it as a type.
 sub _ffi_record_size { $tm_size };
 
 my $ffi = FFI::Platypus->new;
 $ffi->lib(undef);
 # define a record class My::UnixTime and alias it
 # to "tm"
 $ffi->type("record(My::UnixTime)" => 'tm');
 
 # attach the C localtime function as a constructor
 $ffi->attach( [ localtime => '_new' ] => ['time_t*'] => 'tm' );
 
 # the constructor needs to be wrapped in a Perl sub,
 # because localtime is expecting the time_t (if provided)
 # to come in as the first argument, not the second.
 # We could also acomplish something similar using 
 # custom types.
 sub new { _new(\($_[1] || time)) }
 
 # for each attribute that we are interested in, create
 # get and set accessors.  We just make accessors for
 # hour, minute and second, but we could make them for
 # all the fields if we needed.
 foreach my $attr (qw( hour min sec ))
 {
   my $tcc = FFI::TinyCC->new;
   $tcc->compile_string(qq{
     $tm_source
     int
     get_$attr (struct tm *tm)
     {
       return tm->tm_$attr;
     }
     void
     set_$attr (struct tm *tm, int value)
     {
       tm->tm_$attr = value;
     }
   });
   $ffi->attach( [ $tcc->get_symbol("get_$attr") => "get_$attr" ] => [ 'tm' ] => 'int' );
   $ffi->attach( [ $tcc->get_symbol("set_$attr") => "set_$attr" ] => [ 'tm' ] => 'int' );
 }
 
 package main;
 
 # now we can actually use our My::UnixTime class
 my $time = My::UnixTime->new;
 printf "time is %d:%d:%d\n", $time->get_hour, $time->get_min, $time->get_sec;

Contrast a record type which is stored as a scalar string of bytes in 
Perl to an opaque pointer which is stored as an integer in Perl.  Both 
are treated as pointers in C functions.  The situations when you usually 
want to use a record are when you know ahead of time what the size of 
the object that you are working with and probably something about its 
structure.  Because a function that returns a structure copies the 
structure into a Perl data structure, you want to make sure that it is 
okay to copy the record objects that you are dealing with if any of your 
functions will be returning one of them.

Opaque pointers should be used when you do not know the size of the 
object that you are using, or if the objects are created and free'd 
through an API interface other than C<malloc> and C<free>.

=head2 Fixed length arrays

Fixed length arrays of native types are supported by L<FFI::Platypus>.  
Like pointers, if the values contained in the array are updated by the C 
function these changes will be reflected when it returns to Perl space.  
An example of using this is the Unix C<pipe> command which returns a 
list of two file descriptors as an array.

 use FFI::Platypus;
 
 my $ffi = FFI::Platypus->new;
 $ffi->lib(undef);
 $ffi->attach([pipe=>'mypipe'] => ['int[2]'] => 'int');
 
 my @fd = (0,0);
 mypipe(\@fd);
 my($fd1,$fd2) = @fd;
 
 print "$fd1 $fd2\n";

=head2 Variable length arrays

[version 0.22]

Variable length arrays are supported for argument types can also be 
specified by using the C<[]> notation but by leaving the size empty:

 $ffi->type('int[]' => 'var_int_array');

When used as an argument type it will probe the array reference that you 
pass in to determine the correct size.  Usually you will need to 
communicate the size of the array to the C code.  One way to do this is 
to pass the length of the array in as an additional argument.  For 
example the C code:

 int
 sum(int *array, int size)
 {
   int total,i;
   for(i=0,total=0; i<size; i++)
   {
     total += array[i];
   }
   return total;
 }

Can be called from Perl like this:

 use FFI::Platypus;
 
 my $ffi = FFI::Platypus->new;
 $ffi->lib('./var_array.so');
 
 $ffi->attach( sum => [ 'int[]', 'int' ] => 'int' );
 
 my @list = (1..100);
 
 print sum(\@list, scalar @list), "\n";

Another method might be to have a special value, such as 0 or NULL 
indicate the termination of the array.

=head2 Closures

A closure (called a "callback" by L<FFI::Raw>, we use the C<libffi> 
terminology) is a Perl subroutine that can be called from C.  In order 
to be called from C it needs to be passed to a C function.  To define 
the closure type you need to provide a list of argument types and a 
return type.  As of this writing only native types and strings are 
supported as closure argument types and only native types are supported 
as closure return types.  Here is an example, with C code:

 /*
  * closure.c - on Linux compile with: gcc closure.c -shared -o closure.so -fPIC
  */
 
 #include <stdio.h>
 
 typedef int (*closure_t)(int);
 closure_t my_closure = NULL;
 
 void set_closure(closure_t value)
 {
   my_closure = value;
 }
 
 int call_closure(int value)
 {
   if(my_closure != NULL)
     return my_closure(value);
   else
     fprintf(stderr, "closure is NULL\n");
 }

And the Perl code:

 use FFI::Platypus;
 
 my $ffi = FFI::Platypus->new;
 $ffi->lib('./closure.so');
 $ffi->type('(int)->int' => 'closure_t');
 
 $ffi->attach(set_closure => ['closure_t'] => 'void');
 $ffi->attach(call_closure => ['int'] => 'int');
 
 my $closure1 = $ffi->closure(sub { $_[0] * 2 });
 set_closure($closure1);
 print  call_closure(2), "\n"; # prints "4"
 
 my $closure2 = $ffi->closure(sub { $_[0] * 4 });
 set_closure($closure2);
 print call_closure(2), "\n"; # prints "8"

If you have a pointer to a function in the form of an C<opaque> type,
you can pass this in place of a closure type:

 use FFI::Platypus;
 
 my $ffi = FFI::Platypus->new;
 $ffi->lib('./closure.so');
 $ffi->type('(int)->int' => 'closure_t');
 
 $ffi->attach(set_closure => ['closure_t'] => 'void');
 $ffi->attach(call_closure => ['int'] => 'int');
 
 my $closure = $ffi->closure(sub { $_[0] * 6 });
 my $opaque = $ffi->cast(closure_t => 'opaque', $closure);
 set_closure($opaque);
 print call_closure(2), "\n"; # prints "12"

The syntax for specifying a closure type is a list of comma separated 
types in parentheticals followed by a narrow arrow C<-E<gt>>, followed 
by the return type for the closure.  For example a closure that takes a 
pointer, an integer and a string and returns an integer would look like 
this:

 $ffi->type('(opaque, int, string) -> int' => 'my_closure_type');

Care needs to be taken with scoping and closures, because of the way 
Perl and C handle responsibility for allocating memory differently.  
Perl keeps reference counts and frees objects when nothing is 
referencing them.  In C the code that allocates the memory is considered 
responsible for explicitly free'ing the memory for objects it has 
created when they are no longer needed.  When you pass a closure into a 
C function, the C code has a pointer or reference to that object, but it 
has no way up letting Perl know when it is no longer using it. As a 
result, if you do not keep a reference to your closure around it will be 
free'd by Perl and if the C code ever tries to call the closure it will 
probably SIGSEGV.  Thus supposing you have a C function C<set_closure> 
that takes a Perl closure, this is almost always wrong:

 set_closure(closure { $_[0] * 2 });  # BAD

In some cases, you may want to create a closure shouldn't ever be 
free'd.  For example you are passing a closure into a C function that 
will retain it for the lifetime of your application.  You can use the 
sticky keyword to indicate this, without the need to keep a reference of 
the closure:

 set_closure(sticky closure { $_[0] * 2 }); # OKAY 

=head2 Custom Types

=head3 Custom Types in Perl

Platypus custom types are the rough analogue to typemaps in the XS 
world.  They offer a method for converting Perl types into native types 
that the C<libffi> can understand and pass on to the C code.

=head4 Example 1: Integer constants

Say you have a C header file like this:

 /* possible foo types: */
 #define FOO_STATIC  1
 #define FOO_DYNAMIC 2
 #define FOO_OTHER   3
 
 typedef int foo_t;
 
 void foo(foo_t foo);
 foo_t get_foo();

One common way of implementing this would be to create and export 
constants in your Perl module, like this:

 package Foo;
 
 use FFI::Platypus::Declare qw( void int );
 use base qw( Exporter );
 
 our @EXPORT_OK = qw( FOO_STATIC FOO_DYNAMIC FOO_OTHER foo get_foo );
 
 use constant FOO_STATIC  => 1;
 use constant FOO_DYNAMIC => 2;
 use constant FOO_OTHER   => 3;
 
 attach foo => [int] => void;
 attach get_foo => [] => int;

Then you could use the module thus:

 use Foo qw( foo FOO_STATIC );
 foo(FOO_STATIC);

If you didn't want to rely on integer constants or exports, you could 
also define a custom type, and allow strings to be passed into your 
function, like this:

 package Foo;
 
 use FFI::Platypus::Declare qw( void );
 use base qw( Exporter );
 
 our @EXPORT_OK = qw( foo get_foo );
 
 my %foo_types = (
   static  => 1,
   dynamic => 2,
   other   => 3,
 );
 my %foo_types_reverse = reverse %foo_types;
 
 custom_type foo_t => {
   native_type    => 'int',
   native_to_perl => sub {
     $foo_types{$_[0]};
   },
   perl_to_native => sub {
     $foo_types_reverse{$_[0]};
   },
 };
 
 attach foo => ['foo_t'] => void;
 attach get_foo => [] => foo_t;

Now when an argument of type C<foo_t> is called for it will be converted 
from an appropriate string representation, and any function that returns 
a C<foo_t> type will return a string instead of the integer 
representation:

 use Foo;
 foo('static');

=head4 Example 2: Blessed references

Supposing you have a C library that uses an opaque pointer with a pseudo 
OO interface, like this:

 typedef struct foo_t;
 
 foo_t *foo_new();
 void foo_method(foo_t *, int argument);
 void foo_free(foo_t *);

One approach to adapting this to Perl would be to create a OO Perl 
interface like this:

 package Foo;
 
 use FFI::Platypus::Declare
   'void', 'int';
 use FFI::Platypus::API qw( arguments_get_string );
 
 custom_type foo_t => {
   native_type    => 'opaque',
   native_to_perl => sub {
     my $class = arguments_get_string(0);
     bless \$_[0], $class;
   }
   perl_to_native => sub { ${$_[0]} },
 };
 
 attach [ foo_new => 'new' ] => [ string ] => 'foo_t' );
 attach [ foo_method => 'method' ] => [ 'foo_t', int ] => void;
 attach [ foo_free => 'DESTROY' ] => [ 'foo_t' ] => void;
 
 my $foo = Foo->new;

Here we are blessing a reference to the opaque pointer when we return 
the custom type for C<foo_t>, and dereferencing that reference before we 
pass it back in.  The function C<arguments_get_string> queries the C 
arguments to get the class name to make sure the object is blessed into 
the correct class (for more details on the custom type API see 
L<FFI::Platypus::API>), so you can inherit and extend this class like a 
normal Perl class.  This works because the C "constructor" ignores the 
class name that we pass in as the first argument.  If you have a C 
"constructor" like this that takes arguments you'd have to write a 
wrapper for new.

I good example of a C library that uses this pattern, including 
inheritance is C<libarchive>. Platypus comes with a more extensive 
example in C<examples/archive.pl> that demonstrates this.

=head4 Example 3: Pointers with pack / unpack

TODO

See example L<FFI::Platypus::Type::StringPointer>.

=head4 Example 4: Custom Type modules and the Custom Type API

TODO

See example L<FFI::Platypus::Type::PointerSizeBuffer>.

=head4 Example 5: Custom Type on CPAN

You can distribute your own Platypus custom types on CPAN, if you think 
they may be applicable to others.  The default namespace is prefix with 
C<FFI::Platypus::Type::>, though you can stick it anywhere (under your 
own namespace may make more sense if the custom type is specific to your 
application).

A good example and pattern to follow is
L<FFI::Platypus::Type::StringArray>.

=head3 Custom Types in C/XS

Custom types written in C or XS are a future goal of the 
L<FFI::Platypus> project.  They should allow some of the flexibility of 
custom types written in Perl, with potential performance improvements of 
native code.

=head1 SEE ALSO

=over 4

=item L<FFI::Platypus>

Main platypus documentation.

=item L<FFI::Platypus::Declare>

Declarative interface for L<FFI::Platypus>.

=item L<FFI::Platypus::API>

Custom types API.

=item L<FFI::Platypus::Type::StringPointer>

String pointer type.

=back

=head1 AUTHOR

Author: Graham Ollis E<lt>plicease@cpan.orgE<gt>

Contributors:

Bakkiaraj Murugesan (bakkiaraj)

Dylan Cali (calid)

pipcet

Zaki Mughal (zmughal)

Fitz Elliott (felliott)

Vickenty Fesunov (vyf)

Gregor Herrmann (gregoa)

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2015 by Graham Ollis.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut