record#
Declare a record class: a C struct, passed by value or by pointer.
Synopsis#
Peta::FFI::record("My::Point", x => "d", y => "d");
Peta::FFI::record("My::Rect", origin => "{My::Point}", size => "{My::Point}");
my $p = My::Point->new(x => 1.5, y => -2);
print $p->x, "\n"; # 1.5
$p->y(4); # set
# struct Point point_add(struct Point, struct Point);
my $sum = Peta::FFI::call($lib, "point_add", "({My::Point}{My::Point}){My::Point}", $p, $p);
# void point_scale(struct Point *, double);
Peta::FFI::call($lib, "point_scale", "(*{My::Point}d)v", $p, 2);
Members#
Each member is a name and its type, in the order of the C struct: the integer types, f, d, b, o, p (a const char *), a fixed array of numbers or o such as u8[16], and another record by value, {Class}. The layout - each member’s offset and the size and alignment of the whole - is the C compiler’s for the platform, as libffi computes it.
The class#
Class->new(member => value, ...) makes a zeroed record and sets the members given. Each member has an accessor: $r->name reads it, $r->name($value) sets it; an array member also takes ($index), ($index, $value) and an array reference; a record member reads as a copy, an object of its class, and is set from one. A record is a reference to a string of the struct’s bytes, so $$r is them and a record can be built from bytes C produced: bless \$bytes, "My::Point".
A p member reads the string it points to, undef for NULL. Set from Perl, it points to the record’s own copy of the string, which lives as long as the record does or until the member is set again; undef sets NULL. A string C stored in the member is C’s: the record never frees it. Where C moves the strings between records - an array of them it sorts, written back - each goes with the record that points to it, and a record stored into another as its member gives it copies of its own. A bare copy of the record’s bytes points to the same strings but does not keep them.
In a signature {Class} passes and returns the struct by value and *{Class} a pointer to it - the record’s own bytes, which the callee may change in place; undef is NULL.
Edge cases#
A class declared twice - croaks.
A member type a struct cannot hold here (
s,P, a handle, a pointer type, a long double or complex member) - croaks naming it.