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

Я пытаюсь объявить следующую структуру C в Perl 6:

struct myStruct
{
    int A[2]; //<---NEED to declare this
    int B;
    int C;
};

Моя проблема в том, что я не знаю, как объявить int A[2]; часть с использованием встроенного API NativeCall.

Итак, что у меня есть:

class myStruct is repr('CStruct') {
    has CArray[int32] $.A;
    has int32 $.B;
    has int32 $.C;
};

Тем не менее, я знаю, что has CArray[int32] $.A; часть неверна, так как она не объявляет часть в моей структуре, которая занимает ТОЛЬКО 2 int32 размеры.

4 ответа

Обновление 2: оказалось, что это не сработало, когда я впервые опубликовал этот ответ, отсюда и комментарии. Я до сих пор не проверял его, но он наверняка сработает в соответствии с ответом Тобиаса на передачу встроенного CArray в CStruct в общую библиотеку с помощью NativeCall. \ О /


Я не проверял это, но это должно работать при использовании компилятора Rakudo версии 2018.05:

use NativeCall;
class myStruct is repr('CStruct') {
    HAS int32 @.A[2] is CArray;
    has int32 $.B;
    has int32 $.C;
}
  • HAS вместо has заставляет атрибут быть встроенным, а не указателем;

  • int32 вместо int потому что Perl 6 int тип не совпадает с C int тип, но вместо этого зависит от платформы (и обычно 64-битный);

  • @ вместо $ помечает атрибут как Positional ("поддерживает поиск значений по индексу") вместо скаляра (который рассматривается как одна вещь);

  • [2] "формирует" Позиционные данные, чтобы иметь 2 элемента;

  • is CArray связывает CArray как контейнерная логика Позиционных данных;

  • Этот коммит с апреля этого года проводной is repr('CStruct') использовать информацию объявленного атрибута для надлежащего распределения памяти.

Я узнал об этой функции при поиске журналов #perl6 для CArray и обнаружил, что он приземлился в master и 2018.05 из поиска Rakudo фиксирует для заголовка сообщения фиксации.

См. Объявление массива внутри Perl 6 NativeCall CStruct

Есть и другие способы, но проще всего вместо массива просто объявить каждый отдельный элемент.

class myStruct is repr('CStruct') {
    has int32 $.A0;
    has int32 $.A1;
    ... as many items as you need for your array ...
    has int32 $.B;
    has int32 $.C;
};

Итак, я провел некоторые эксперименты по этому вопросу и взглянул на документы, и похоже, что тип CArray не обрабатывает формирование так же, как Perl6 Arrays.

Самое близкое, что у вас есть, - это конструктор allocate, который предварительно выделяет пространство в массиве, но не устанавливает размер, поэтому вы можете добавлять больше вещей.

Ваше определение класса в порядке, но вы хотите выделить массив в BUILD submethod.

https://docs.perl6.org/language/nativecall

(Дальше думал)

Вы могли бы иметь два объекта. Один внутренний и один для структуры.

Структура имеет CArray[int32] массив. Внутренний объект данных имеет фасонный массив типов int32 my int3 @a[2], Тогда вам просто нужно скопировать между ними.

Получатели и установщики живут на главном объекте, и вы используете объект struct только тогда, когда хотите поговорить с библиотекой lib?

Это на самом деле не объявляет массив фиксированного размера, но накладывает ограничение на размер его значения: вы можете попробовать и использовать where ограничить размер массива. CArray не является позиционным (и, следовательно, не может быть объявлен с @ сигил) но у него есть elems метод.

use NativeCall; 
my CArray[int32] $A where .elems < 2

Это, по крайней мере, синтаксически правильно. Будет ли это нарушать программу в каком-то другом месте, еще неизвестно. Вы можете попробовать это?

Другие вопросы по тегам