Передача встроенного CArray в CStruct в общую библиотеку с помощью NativeCall - PullRequest
0 голосов
/ 09 июня 2018

Это дополнительный вопрос к " Как объявить собственный массив фиксированного размера в Perl 6? ".

В этом вопросе он обсуждалсяКак включить массив фиксированного размера в CStruct этом ответе было предложено использовать HAS для встраивания CArray в CStruct.Когда я проверил эту идею, я столкнулся с каким-то странным поведением, которое не может быть разрешено в разделе комментариев ниже вопроса, поэтому я решил написать его как новый вопрос.Вот мой код библиотеки C test:

slib.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

Затем код Perl 6:

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?

Примечание :

IЯ использую Ubuntu 18.04 и Perl 6 Rakudo версии 2018.04.01, но также протестировал версию 2018.05

1 Ответ

0 голосов
/ 07 августа 2018

Ваш код правильный.Я только исправил эту ошибку в MoarVM и добавил тесты в rakudo, аналогично вашему коду:

В C:

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

В Perl 6:

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

Если вы не создаете rakudo (а также NQP и MoarVM) непосредственно из последнего источника из githubвам, вероятно, придется дождаться выпуска 2018.08, который появится здесь: https://rakudo.org/files

...