代码之家  ›  专栏  ›  技术社区  ›  Håkon Hægland

使用nativeCall将cstruct中的内联carray传递给共享库

  •  5
  • Håkon Hægland  · 技术社区  · 6 年前

    这是一个后续问题 How to declare native array of fixed size in Perl 6? “。

    在这个问题中,讨论了如何将固定大小的数组合并到 CStruct . 在 this answer 建议使用 HAS 嵌入 CArray C结构 . 当我测试这个想法时,我遇到了一些奇怪的行为,这些行为在问题下面的评论部分无法解决,所以我决定把它写成一个新问题。这是我的C测试库代码:

    滑动C :

    #include <stdio.h>
    
    struct myStruct
    {
        int A; 
        int B[3];
        int C;
    };
    
    void use_struct (struct myStruct *s) {
        printf("sizeof(struct myStruct): %ld\n", sizeof( struct myStruct ));
        printf("sizeof(struct myStruct *): %ld\n", sizeof( struct myStruct *));
        printf("A = %d\n", s->A);
        printf("B[0] = %d\n", s->B[0]);
        printf("B[1] = %d\n", s->B[1]);
        printf("B[2] = %d\n", s->B[2]);
        printf("C = %d\n", s->C);
    }
    

    要从中生成共享库,我使用了:

    gcc -c -fpic slib.c
    gcc -shared -o libslib.so slib.o
    

    然后,Perl6代码:

    P.P6 :

    use v6;
    use NativeCall;
    
    class myStruct is repr('CStruct') {
        has int32 $.A is rw;
        HAS int32 @.B[3] is CArray is rw;
        has int32 $.C is rw;
    }
    
    sub use_struct(myStruct $s) is native("./libslib.so") { * };
    
    my $s = myStruct.new();
    $s.A = 1;
    $s.B[0] = 2;
    $s.B[1] = 3;
    $s.B[2] = 4;
    $s.C = 5;
    say "Expected size of Perl 6 struct: ", (nativesizeof(int32) * 5);
    say "Actual size of Perl 6 struct: ", nativesizeof( $s );
    say 'Number of elements of $s.B: ', $s.B.elems;
    say "B[0] = ", $s.B[0];
    say "B[1] = ", $s.B[1];
    say "B[2] = ", $s.B[2];
    say "Calling library function..";
    say "--------------------------";
    use_struct( $s );
    

    脚本的输出是:

    Expected size of Perl 6 struct: 20
    Actual size of Perl 6 struct: 24
    Number of elements of $s.B: 3
    B[0] = 2
    B[1] = 3
    B[2] = 4
    Calling library function..
    --------------------------
    sizeof(struct myStruct): 20
    sizeof(struct myStruct *): 8
    A = 1
    B[0] = 0         # <-- Expected 2
    B[1] = 653252032 # <-- Expected 3
    B[2] = 22030     # <-- Expected 4
    C = 5
    

    问题 :

    • 为什么? nativesizeof( $s ) 给出24(而不是预期值20)?

    • 为什么数组的内容是 B 在从C函数打印时结构是否与预期不符?

    注释 :

    我使用的是Ubuntu 18.04和Perl6 Rakudo版本2018.04.01,但也使用了版本2018.05进行了测试。

    1 回复  |  直到 6 年前
        1
  •  5
  •   Tobias Leich    6 年前

    typedef struct {
        int a;
        int b[3];
        int c;
    } InlinedArrayInStruct;
    

    class InlinedArrayInStruct is repr('CStruct') {
        has int32 $.a is rw;
        HAS int32 @.b[3] is CArray;
        has int32 $.c is rw;
    }
    

    https://github.com/MoarVM/MoarVM/commit/ac3d3c76954fa3c1b1db14ea999bf3248c2eda1c https://github.com/rakudo/rakudo/commit/f8b79306cc1900b7991490eef822480f304a56d9

    https://rakudo.org/files

    推荐文章