Как объявить собственный массив фиксированного размера в 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 6int
тип не совпадает с Cint
тип, но вместо этого зависит от платформы (и обычно 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
Это, по крайней мере, синтаксически правильно. Будет ли это нарушать программу в каком-то другом месте, еще неизвестно. Вы можете попробовать это?