2017-05-30 112 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

相關問題