Create_an_object_at_a_given_address.md 2.1 KB

Create an object at a given address

Perl 6 has fairly comprehensive facilities for accessing allocating and accessing memory and also declaring C-style structs, via the NativeCall interface, as this example demonstrates.

use v6;
use NativeCall;
use NativeCall::Types;
 
# bind to basic libc memory management
sub malloc(size_t) returns Pointer[uint8] is native {*};
sub memset(Pointer, uint32, size_t) is native {*};
sub free(Pointer[uint8]) is native {*};
 
my Pointer[uint8] $base-p = malloc(100);
memset($base-p, 0, 100);
 
# define object as a C struct that contains a short and an int
class SampleObject is repr('CStruct') {
    has uint16 $.foo is rw;
    has uint8  $.bar is rw;
}
 
# for arguments sake our object is at byte offset 64 in the
# allocated memory
 
my $offset-p =  $base-p.clone.add(64);
my $object-p := nativecast(Pointer[SampleObject], $offset-p);
note "creating object at address {+$object-p}";
 
my $struct := $object-p.deref;
 
$struct.foo = 41;
$struct.bar = 99;
 
# check we can update
$struct.foo++; # 42
 
# Check that we're actually updating the memory
use Test;
 
# look at the bytes directly to verify we've written to memory. Don't be too exact, as
# the positions may vary on different platforms depending on endianess and field alignment.
 
my $rec-size = nativesizeof(SampleObject);
my uint8 @bytes-written = (0 ..^ $rec-size).map(-> $i {$base-p[64 + $i]}).grep: * > 0;
 
# first field 'foo' (amount is small enough to fit in one byte)
is @bytes-written[0], 42, 'object first field';
 
# second field 'bar'
is @bytes-written[1], 99, 'object second field';
 
# verify that changing the origin changes the object values
memset($base-p, 1, 100); # set every byte to 1
 
is $struct.foo, 256 + 1, 'short updated at origin';
is $struct.bar, 1, 'byte updated at origin';
 
# tidy up
free($base-p);
done-testing;
 

Output:

creating object at address 94299589110352
ok 1 - object first field
ok 2 - object second field
ok 3 - short updated at origin
ok 4 - byte updated at origin
1..4