Skip to content

Instantly share code, notes, and snippets.

@Xliff
Last active June 25, 2016 22:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Xliff/96e48eaad469e42e3c604380a73a918a to your computer and use it in GitHub Desktop.
Save Xliff/96e48eaad469e42e3c604380a73a918a to your computer and use it in GitHub Desktop.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment