Codebase list libffi-platypus-perl / 2a4d737
add opaque object example Graham Ollis authored 1 year, 6 months ago Graham✈️✈️ committed 1 year, 6 months ago
4 changed file(s) with 184 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
11101110 returned to Perl as a reference to a scalar. Platypus also supports string
11111111 pointers (`string*`). (Though the C equivalent to a `string*` is a double
11121112 pointer to char `char**`).
1113
1114 ## Opaque Pointers (objects)
1115
1116 ### C Source
1117
1118 ```
1119 #include <string.h>
1120 #include <stdlib.h>
1121
1122 typedef struct person_t {
1123 char *name;
1124 unsigned int age;
1125 } person_t;
1126
1127 person_t *
1128 person_new(const char *name, unsigned int age) {
1129 person_t *self = malloc(sizeof(person_t));
1130 self->name = strdup(name);
1131 self->age = age;
1132 }
1133
1134 const char *
1135 person_name(person_t *self) {
1136 return self->name;
1137 }
1138
1139 unsigned int
1140 person_age(person_t *self) {
1141 return self->age;
1142 }
1143
1144 void
1145 person_free(person_t *self) {
1146 free(self->name);
1147 free(self);
1148 }
1149 ```
1150
1151 ### Perl Source
1152
1153 ```perl
1154 use FFI::Platypus 2.00;
1155
1156 my $ffi = FFI::Platypus->new(
1157 api => 2,
1158 lib => './person.so',
1159 );
1160
1161 $ffi->type( 'opaque' => 'person_t' );
1162
1163 $ffi->attach( person_new => ['string','unsigned int'] => 'person_t' );
1164 $ffi->attach( person_name => ['person_t'] => 'string' );
1165 $ffi->attach( person_age => ['person_t'] => 'unsigned int' );
1166 $ffi->attach( person_free => ['person_t'] );
1167
1168 my $person = person_new( 'Roger Frooble Bits', 35 );
1169
1170 print "name = ", person_name($person), "\n";
1171 print "age = ", person_age($person), "\n";
1172
1173 person_free($person);
1174 ```
1175
1176 ### Execute
1177
1178 ```
1179 $ gcc -shared -o person.so person.c
1180 $ perl person.pl
1181 name = Roger Frooble Bits
1182 age = 35
1183 ```
1184
1185 ### Discussion
1186
1187 An opaque pointer is a pointer (memory address) that is pointing to _something_
1188 but you do not know the structure of that something. In C this is usually a
1189 `void*`, but it could also be a pointer to a `struct` without a defined body.
1190
1191 This is often used to as an abstraction around objects in C. Here in the C
1192 code we have a `person_t` struct with functions to create (a constructor), free
1193 (a destructor) and query it (methods).
1194
1195 The Perl code can then use the constructor, methods and destructors without having
1196 to understand the internals. The `person_t` internals can also be changed
1197 without having to modify the calling code.
1198
1199 We use the Platypus [type method](#type) to create an alias of `opaque` called
1200 `person_t`. While this is not necessary, it does make the Perl code easier
1201 to understand.
1202
1203 In later examples we will see how to hide the use of `opaque` types further
1204 using the `object` type, but for some code direct use of `opaque` is
1205 appropriate.
11131206
11141207 ## Arrays
11151208
0 #include <string.h>
1 #include <stdlib.h>
2
3 typedef struct person_t {
4 char *name;
5 unsigned int age;
6 } person_t;
7
8 person_t *
9 person_new(const char *name, unsigned int age) {
10 person_t *self = malloc(sizeof(person_t));
11 self->name = strdup(name);
12 self->age = age;
13 }
14
15 const char *
16 person_name(person_t *self) {
17 return self->name;
18 }
19
20 unsigned int
21 person_age(person_t *self) {
22 return self->age;
23 }
24
25 void
26 person_free(person_t *self) {
27 free(self->name);
28 free(self);
29 }
0 use strict;
1 use warnings;
2 use FFI::Platypus 2.00;
3
4 my $ffi = FFI::Platypus->new(
5 api => 2,
6 lib => './person.so',
7 );
8
9 $ffi->type( 'opaque' => 'person_t' );
10
11 $ffi->attach( person_new => ['string','unsigned int'] => 'person_t' );
12 $ffi->attach( person_name => ['person_t'] => 'string' );
13 $ffi->attach( person_age => ['person_t'] => 'unsigned int' );
14 $ffi->attach( person_free => ['person_t'] );
15
16 my $person = person_new( 'Roger Frooble Bits', 35 );
17
18 print "name = ", person_name($person), "\n";
19 print "age = ", person_age($person), "\n";
20
21 person_free($person);
15131513 pointers (C<string*>). (Though the C equivalent to a C<string*> is a double
15141514 pointer to char C<char**>).
15151515
1516 =head2 Opaque Pointers (objects)
1517
1518 =head3 C Source
1519
1520 # EXAMPLE: examples/person.c
1521
1522 =head3 Perl Source
1523
1524 # EXAMPLE: examples/person.pl
1525
1526 =head3 Execute
1527
1528 $ gcc -shared -o person.so person.c
1529 $ perl person.pl
1530 name = Roger Frooble Bits
1531 age = 35
1532
1533 =head3 Discussion
1534
1535 An opaque pointer is a pointer (memory address) that is pointing to I<something>
1536 but you do not know the structure of that something. In C this is usually a
1537 C<void*>, but it could also be a pointer to a C<struct> without a defined body.
1538
1539 This is often used to as an abstraction around objects in C. Here in the C
1540 code we have a C<person_t> struct with functions to create (a constructor), free
1541 (a destructor) and query it (methods).
1542
1543 The Perl code can then use the constructor, methods and destructors without having
1544 to understand the internals. The C<person_t> internals can also be changed
1545 without having to modify the calling code.
1546
1547 We use the Platypus L<type method|/type> to create an alias of C<opaque> called
1548 C<person_t>. While this is not necessary, it does make the Perl code easier
1549 to understand.
1550
1551 In later examples we will see how to hide the use of C<opaque> types further
1552 using the C<object> type, but for some code direct use of C<opaque> is
1553 appropriate.
1554
15161555 =head2 Arrays
15171556
15181557 =head3 C Source