Как объявить собственный массив фиксированного размера в Perl 6? - PullRequest
0 голосов
/ 06 июня 2018

Я пытаюсь объявить следующую структуру 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; неверна, поскольку она не объявляет часть в моей структуре, которая занимает ТОЛЬКО 2int32 размеры.

Ответы [ 4 ]

0 голосов
/ 07 июня 2018

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


Я не проверял это, но это должно работать при использовании компилятора 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 не совпадает с типом Cint тип, но вместо этого зависит от платформы (и обычно 64-битный);

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

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

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

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

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

0 голосов
/ 06 июня 2018

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

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

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

0 голосов
/ 07 июня 2018

См. Объявление массива в 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;
};
0 голосов
/ 06 июня 2018

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

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

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

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

(дальнейшие размышления)

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

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

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

...