结构数组作为Perl 6 NativeCall结构的属性

Fer*_*ata 9 arrays perl6 nativecall raku

我正在尝试封装一个C结构,其中一个成员是一个指向结构的指针数组,而我在弄清楚如何执行它时遇到了问题.

假设C代码如下所示:

struct foo
{
  unsigned char a;
};

struct bar
{
  struct foo *f[5];
};
Run Code Online (Sandbox Code Playgroud)

这种代码有效:

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;
}
Run Code Online (Sandbox Code Playgroud)

但它太可怕了.

A CArray在这里没用,因为它只是一个指向数组的指针,而不是一个指针数组; 我不能使用类似的东西has A @.a,因为a repr('CStruct')不处理那种属性.

任何提示?

ara*_*ren 2

我为此编写了一个示例代码。C面:

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;
}
Run Code Online (Sandbox Code Playgroud)

由于 Rakudo 不支持从 C 端获取堆栈变量,因此您应该使用 mallocstruct bar在堆上分配 a。

然后用gcc编译代码,例如gcc -shared -fPIC -o libshasa.so xxx.c.

这是 Perl6 方面:

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;
Run Code Online (Sandbox Code Playgroud)

这输出:

GET A CHAR => 0x61 = a
CREATE BAR PTR OK
97
98
99
100
101
Run Code Online (Sandbox Code Playgroud)