So I have this shared lib code:
/* testNodeSet.c */
#include <stdlib.h>
struct nodeStruct {
int foo;
int bar;
int baz;
};
typedef struct nodeStruct nodeStruct;
typedef struct testStruct testStruct;
struct testStruct {
testStruct *fe;
testStruct *fi;
testStruct *fo;
nodeStruct *fum;
};
testStruct *createTestStruct() {
nodeStruct *newNode;
testStruct *newTest;
newNode = (nodeStruct *)malloc(sizeof(nodeStruct));
newNode->foo = 42;
newNode->bar = -1;
newNode->baz = 23;
newTest = (testStruct *)malloc(sizeof(testStruct));
newTest->fe = newTest;
newTest->fi = (testStruct *)malloc(sizeof(testStruct));
newTest->fo = NULL;
newTest->fum = newNode;
return newTest;
}
Which I've compiled into a shared lib:
gcc -shared -fPIC -o libtestnode.so testNodeSet.c
And this perl6 code:
use v6.c;
use NativeCall;
use Test;
class nodeStruct is repr('CStruct') {
has int32 $.foo;
has int32 $.bar;
has int32 $.baz;
method setFoo($_foo) {
$!foo = $_foo;
}
method setBar($_bar) {
$!bar = $_bar;
}
method setBaz($_baz) {
$!baz = $_baz;
}
}
class testStruct is repr('CStruct') { ... };
class testStruct {
has testStruct $.fe;
has testStruct $.fi;
has testStruct $.fo;
has nodeStruct $.fum;
method setFe($_fe) {
$!fe = $_fe;
}
method setFi($_fi) {
$!fi = $_fi;
}
method setFo($_fo) {
$!fo = $_fo;
}
method setFum($_fum) {
$!fum = $_fum;
}
}
sub createTestStruct() is native("./testnode") returns testStruct { * }
my $test = createTestStruct;
$test.setFe(testStruct.new);
$test.setFi(testStruct.new);
$test.setFo(testStruct.new);
my $fum = $test.fum;
$fum.setFoo(1138);
$fum.setBar(90210);
$fum.setBaz(8675309);
$test.setFum(nodeStruct.new);
say "Done!";
And when I run the script, I get this:
$ perl6 testnode.pl6
Cannot assign to an immutable value
in method setFe at testnode.pl6 line 31
in block <unit> at testnode.pl6 line 51
Turns out that when you are trying to set an attribute in a CStruct repr, you need to use nqp. So the set methods will need to look more like this:
method setFoo($_foo) {
nqp::bindattr(nqp::decont($_foo), testStruct, '$!foo', nqp::decont(self));
}
Thanks to FROGGS on freenode/#perl6 for this bit of wisdom.