2017-05-30 83 views
8

我想封装一个C结构体,其中的一个成员是指向结构体的指针数组,并且我有问题想出如何去做。结构数组作为Perl 6的一个属性NativeCall结构

假设C代码如下所示:

struct foo 
{ 
    unsigned char a; 
}; 

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

这种代码的工作:

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; 
} 

但它是可怕的。因为它只是指向数组的指针,而不是指针数组;我不能使用类似has A @.a的东西,因为repr('CStruct')不处理那种属性。

任何提示?

回答

1

我为此写了一个示例代码。 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; 
} 

因为Rakudo不支持获取从C面堆栈变量,你应该使用malloc在堆中分配struct bar

然后用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; 

此输出:

GET A CHAR => 0x61 = a 
CREATE BAR PTR OK 
97 
98 
99 
100 
101 
+0

我试图让成这个样子了'类酒吧是再版( 'CStruct'){具有FOO @ .a}',这是不正确的语法,因为'foo'不是使用NativeCall的可接受的属性类型。 –

+0

@FernandoSantagata当然,它不是支持,Rakudo的数组与C数组(分配在堆栈上)有不同的内存布局。我想找到一种方法来做到这一点(使用元对象协议自动添加属性与元对象协议,模拟一个数组),但没有关于创建或手动操作角色的文档,或添加一个属性(由HAS声明)采用元对象协议方式。也许你可以发邮件给Rakudo核心开发者。 – araraloren

相关问题