9

I'm trying to encapsulate a C struct, one member of which is an array of pointers to structs, and I'm having problems figuring out how to do it.

Let's say the C code looks like this:

struct foo
{
  unsigned char a;
};

struct bar
{
  struct foo *f[5];
};

This kind of code works:

use NativeCall;

class foo is repr('CStruct') {
  has uint8 $.a;
}

class bar is repr('CStruct') {
  has foo $.f1;
  has foo $.f2;
  has foo $.f3;
  has foo $.f4;
  has foo $.f5;
}

but it's terrible.

A CArray is of no use here, because it's just a pointer to an array, not an array of pointers; I can't use something like has A @.a, because a repr('CStruct') doesn't handle that kind of attribute.

Any hint?

Pat
  • 36,282
  • 18
  • 72
  • 87
Fernando Santagata
  • 1,487
  • 1
  • 8
  • 15

1 Answers1

2

I write a sample code for this. The C side:

struct bar* create_bar_ptr(unsigned char a)
{
    printf("GET A CHAR => %#0x = %c\n", a, a);

    struct bar* bar = (struct bar*)malloc(sizeof(struct bar));

    for (size_t i = 0;i < 5;i ++) {
        struct foo* tf = (struct foo*)malloc(sizeof(struct foo));

        tf->a = a + i;
        bar->f[i] = tf; 
    }

    printf("CREATE BAR PTR OK\n");

    return bar;
}

Because Rakudo does not support getting a stack variable from C side, you should use malloc allocate a struct bar on the heap.

Then compile code with gcc, such as gcc -shared -fPIC -o libshasa.so xxx.c.

And this is Perl6 side:

use NativeCall;

class foo is repr('CStruct') {
    has uint8 $.a;
}

class bar is repr('CStruct') {
    # Here you should use !!HAS!!, not has
    HAS Pointer[foo] $.f1;
    HAS Pointer[foo] $.f2;
    HAS Pointer[foo] $.f3;
    HAS Pointer[foo] $.f4;
    HAS Pointer[foo] $.f5;
}


sub create_bar_ptr(uint8) returns Pointer[bar] is native('./libshasa.so') { * }

my Pointer[bar] $p = create_bar_ptr(uint8.new(97));

say $p.deref."f{$_}"().deref.a for 1 .. 5;

This outputs:

GET A CHAR => 0x61 = a
CREATE BAR PTR OK
97
98
99
100
101
araraloren
  • 185
  • 7
  • What I was trying to get was something like this `class bar is repr('CStruct') { has foo @.a }`, which is not a correct syntax, since `foo` is not an accepted attribute type using NativeCall. – Fernando Santagata May 31 '17 at 17:53
  • @FernandoSantagata Of course it's not support that, Rakudo's array has different memory layout with C array(allocated on the stack). I want find a way to do that( automate add attribute with meta-object protocol, emulate an array ) with meta-object protocol, but there are no document about create or manual manipulation a role, or add a attribute(declared by HAS) in meta-object protocol way. Maybe you can send a question email to Rakudo core developer. – araraloren Jun 01 '17 at 02:13