Spec-Zone.ru › Perl 5.30

perlxstypemap

СОДЕРЖАНИЕ

  • ИМЯ
  • ОПИСАНИЕ
    • Структура typemap
    • Роль файла typemap в вашем дистрибутиве
    • Обмен typemap между дистрибутивами CPAN
    • Написание записей typemap
    • Полный список основных typemap

ИМЯ

perlxstypemap - Сопоставление типов C/Perl в Perl XS

ОПИСАНИЕ

Чем больше вы думаете о взаимодействии между двумя языками, тем больше вы осознаете, что большая часть усилий программиста должна быть направлена на преобразование между структурами данных, которые являются основными для каждого из участвующих языков. Это преобладает над другими вопросами, такими как различия в соглашениях о вызовах, поскольку пространство проблем намного больше. Существует просто больше способов размещения данных в памяти, чем способов реализации вызова функции.

Попытка Perl XS решить эту проблему заключается в концепции typemap. На абстрактном уровне Perl XS typemap — это всего лишь рецепт преобразования из определенной структуры данных Perl в определенную структуру данных C и наоборот. Поскольку могут быть типы C, которые достаточно похожи друг на друга, чтобы оправдать преобразование с помощью одного и того же алгоритма, typemap XS представлены уникальным идентификатором, который в дальнейшем в этом документе называется типом XS. Затем вы можете сообщить компилятору XS, что несколько типов C должны быть сопоставлены с одним и тем же typemap XS.

В вашем коде XS, когда вы определяете аргумент с типом C или когда вы используете CODE: и OUTPUT: разделы вместе с типом возвращаемого значения C вашего XSUB, механизм сопоставления типов сделает это легко.

Структура typemap

В более практическом плане typemap представляет собой набор фрагментов кода, используемых компилятором xsubpp для сопоставления параметров и значений функций C со значениями Perl. Файл typemap может состоять из трех разделов, помеченных TYPEMAP, INPUT, и OUTPUT. Предполагается, что начальный раздел без метки является разделом TYPEMAP. Раздел INPUT сообщает компилятору, как преобразовывать значения Perl в переменные определенных типов C. Раздел OUTPUT сообщает компилятору, как преобразовывать значения из определенных типов C в значения, которые Perl может понять. Раздел TYPEMAP сообщает компилятору, какие фрагменты кода INPUT и OUTPUT следует использовать для сопоставления данного типа C со значением Perl. Метки разделов TYPEMAP, INPUT, или OUTPUT должны начинаться в первой колонке на отдельной строке и должны быть заглавными.

Каждый тип раздела может появляться любое количество раз и вообще не должен появляться. Например, typemap может часто отсутствовать INPUT и OUTPUT разделы, если ему нужно только связать дополнительные типы C с основными типами XS, такими как T_PTROBJ. Строки, начинающиеся с символа решётки #, считаются комментариями и игнорируются в разделе TYPEMAP, но являются значимыми в разделах INPUT и OUTPUT. Пустые строки, как правило, игнорируются.

Традиционно, typemap необходимо было записывать в отдельный файл, обычно называемый typemap в дистрибутиве CPAN. С версией ExtUtils::ParseXS (компилятор XS) 3.12 или выше, которая поставляется с perl 5.16, typemap также можно встраивать непосредственно в код XS, используя синтаксис типа HERE-doc:

TYPEMAP: <<HERE
...
HERE

где HERE можно заменить другими идентификаторами, как и в обычных Perl HERE-doc. Все детали ниже о текстовом формате typemap остаются действительными.

Раздел TYPEMAP должен содержать одну пару типа C и типа XS на строке следующим образом. Пример из файла основного typemap:

TYPEMAP
# all variants of char* is handled by the T_PV typemap
char *          T_PV
const char *    T_PV
unsigned char * T_PV
...

Разделы INPUT и OUTPUT имеют идентичный формат, то есть каждая неотступленная строка начинает новую карту ввода или вывода соответственно. Новая карта ввода или вывода должна начинаться с имени сопоставляемого типа XS на отдельной строке, за которым следует код, реализующий его, отступленный на следующих строках. Пример:

INPUT
T_PV
  $var = ($type)SvPV_nolen($arg)
T_PTR
  $var = INT2PTR($type,SvIV($arg))

Мы немного расскажем о значении этих похожих на Perl переменных.

Наконец, вот пример полного файла typemap для сопоставления C-строк типа char * со скалярными значениями/строками Perl:

TYPEMAP
char *  T_PV

INPUT
T_PV
  $var = ($type)SvPV_nolen($arg)

OUTPUT
T_PV
  sv_setpv((SV*)$arg, $var);

Вот более сложный пример: предположим, что вы хотели, чтобы struct netconfig был благословлён в класс Net::Config. Один из способов сделать это — использовать символы подчеркивания (_) для разделения имён пакетов, как показано ниже:

typedef struct netconfig * Net_Config;

А затем предоставить запись typemap T_PTROBJ_SPECIAL, которая сопоставляет подчеркивания с двойными двоеточиями (::), и объявить Net_Config как такого типа:

TYPEMAP
Net_Config      T_PTROBJ_SPECIAL

INPUT
T_PTROBJ_SPECIAL
  if (sv_derived_from($arg, \"${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\")){
    IV tmp = SvIV((SV*)SvRV($arg));
    $var = INT2PTR($type, tmp);
  }
  else
    croak(\"$var is not of type ${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\")

OUTPUT
T_PTROBJ_SPECIAL
  sv_setref_pv($arg, \"${(my $ntt=$ntype)=~s/_/::/g;\$ntt}\",
               (void*)$var);

Разделы INPUT и OUTPUT подставляют символы подчеркивания двойными двоеточиями на лету, что даёт желаемый эффект. Этот пример демонстрирует некоторые возможности и универсальность механизма typemap.

Макрос INT2PTR (определённый в perl.h) преобразует целое число в указатель заданного типа, учитывая возможные различия в размере целых чисел и указателей. Также существуют PTR2IV, PTR2UV, PTR2NV макросы для преобразования в обратном направлении, что может быть полезно в разделах OUTPUT.

Роль файла typemap в вашем дистрибутиве

Файл typemap по умолчанию в каталоге lib/ExtUtils исходного кода Perl содержит множество полезных типов, которые могут быть использованы Perl-расширениями. Некоторые расширения определяют дополнительные typemap, которые хранятся в своих каталогах. Эти дополнительные typemap могут ссылаться на карты ввода и вывода в основном typemap. Компилятор xsubpp позволит typemap расширения переопределять любые сопоставления, которые находятся в основном typemap. Вместо использования дополнительного файла typemap, typemap можно встроить непосредственно в XS с помощью синтаксиса heredoc. См. документацию по ключевому слову TYPEMAP: XS.

Для дистрибутивов CPAN можно предположить, что типы XS, определённые ядром Perl, уже доступны. Кроме того, в основном typemap имеются значения XS по умолчанию для большого числа типов C. Например, если вы просто вернёте char * из вашего XSUB, в основном typemap будет этот тип C, связанный с типом XS T_PV. Это означает, что ваша C-строка будет скопирована в слот PV (значение указателя) нового скаляра, который будет возвращён из вашего XSUB в Perl.

Если вы разрабатываете дистрибутив CPAN с использованием XS, вы можете добавить свой собственный файл под названием typemap в дистрибутив. Этот файл может содержать typemap, которые либо сопоставляют типы, специфичные для вашего кода, либо переопределяют сопоставления файла основного typemap для общих типов C.

Обмен typemap между дистрибутивами CPAN

Начиная с версии ExtUtils::ParseXS 3.13_01 (поставляется с perl 5.16 и новее), обмен кодом typemap между несколькими дистрибутивами CPAN довольно прост. Основная идея состоит в том, чтобы разделить его как модуль, который предоставляет определённый API, и заставить зависимые модули объявить это как требование времени компиляции и импортировать typemap в XS. Примером такого модуля обмена typemap на CPAN является ExtUtils::Typemaps::Basic. Два шага для того, чтобы сделать typemap этого модуля доступными в вашем коде:

  • Объявите ExtUtils::Typemaps::Basic как зависимость времени компиляции в Makefile.PL (используйте BUILD_REQUIRES), или в вашем Build.PL (используйте build_requires).

  • Включите следующую строку в раздел XS вашего файла XS: (не разрывайте строку)

    INCLUDE_COMMAND: $^X -MExtUtils::Typemaps::Cmd
                     -e "print embeddable_typemap(q{Basic})"

Написание записей typemap

Каждая запись typemap INPUT или OUTPUT представляет собой двойную Perl-строку, которая будет вычислена при наличии определённых переменных, чтобы получить окончательный C-код для сопоставления определённого типа C.

Это означает, что вы можете встраивать Perl-код в ваш код typemap (C) с использованием конструкций, таких как ${ perl code that evaluates to scalar reference here }. Общий случай использования — создание сообщений об ошибках, которые ссылаются на истинное имя функции даже при использовании функции ALIAS XS:

${ $ALIAS ? \q[GvNAME(CvGV(cv))] : \qq[\"$pname\"] }

Для получения многих примеров typemap обратитесь к файлу основного typemap, который находится в дереве исходного кода Perl в каталоге lib/ExtUtils/typemap.

Переменные Perl, которые доступны для интерполяции в typemap, следующие:

  • $var - имя входной или выходной переменной, например RETVAL для значений возврата.

  • $type - исходный тип C параметра, любой : заменён на _. Например, для типа Foo::Bar, $type является Foo__Bar

  • $ntype - предоставленный тип с * заменён на Ptr. Например, для типа Foo*, $ntype является FooPtr

  • $arg - запись стека, из которой параметр вводится или в которую выводится, например ST(0)

  • $argoff - смещение аргумента в стеке аргументов. То есть 0 для первого аргумента и т.д.

  • $pname - полное имя XSUB, включая имя PACKAGE, с любым PREFIX удалено. Это имя без ALIAS.

  • $Package - пакет, указанный последним ключевым словом PACKAGE

  • $ALIAS - не равно нулю, если у текущего XSUB есть какие-либо псевдонимы, объявленные с ALIAS.

Полный список основных typemap

Каждый тип C представлен записью в файле typemap, которая отвечает за преобразование переменных Perl (SV, AV, HV, CV и т. д.) в этот тип и из него. В следующих разделах перечислены все типы XS, которые поставляются с Perl по умолчанию.

T_SV

Это просто передаёт C-представление переменной Perl (SV*) внутрь и наружу слоя XS. Это можно использовать, если C-код хочет работать напрямую с переменной Perl.

T_SVREF

Используется для передачи и возврата ссылки на SV.

Обратите внимание, что эта карта типов не уменьшает счётчик ссылок при возврате ссылки на SV*. См. также: T_SVREF_REFCOUNT_FIXED

T_SVREF_FIXED

Используется для передачи и возврата ссылки на SV. Это фиксированная разновидность T_SVREF, которая корректно уменьшает счётчик ссылок при возврате ссылки на SV*. Введено в perl 5.15.4.

T_AVREF

На уровне Perl это ссылка на массив Perl. На уровне C это указатель на AV.

Обратите внимание, что эта карта типов не уменьшает счётчик ссылок при возврате AV*. См. также: T_AVREF_REFCOUNT_FIXED

T_AVREF_REFCOUNT_FIXED

На уровне Perl это ссылка на массив Perl. На уровне C это указатель на AV. Это фиксированная разновидность T_AVREF, которая корректно уменьшает счётчик ссылок при возврате AV*. Введено в perl 5.15.4.

T_HVREF

На уровне Perl это ссылка на хеш Perl. На уровне C это указатель на HV.

Обратите внимание, что эта карта типов не уменьшает счётчик ссылок при возврате HV*. См. также: T_HVREF_REFCOUNT_FIXED

T_HVREF_REFCOUNT_FIXED

На уровне Perl это ссылка на хеш Perl. На уровне C это указатель на HV. Это фиксированная разновидность T_HVREF, которая корректно уменьшает счётчик ссылок при возврате HV*. Введено в perl 5.15.4.

T_CVREF

На уровне Perl это ссылка на подпрограмму Perl (например, $sub = подпрограмма { 1 };). На уровне C это указатель на CV.

Обратите внимание, что эта карта типов не уменьшает счётчик ссылок при возврате HV*. См. также: T_HVREF_REFCOUNT_FIXED

T_CVREF_REFCOUNT_FIXED

На уровне Perl это ссылка на подпрограмму Perl (например, $sub = подпрограмма { 1 };). На уровне C это указатель на CV.

Это фиксированная разновидность T_HVREF, которая корректно уменьшает счётчик ссылок при возврате HV*. Введено в perl 5.15.4.

T_SYSRET

Карта типов T_SYSRET используется для обработки возвращаемых значений из системных вызовов. Она имеет смысл только при передаче значений из C в Perl (нет понятия передачи значения системного возврата из Perl в C).

Системные вызовы возвращают -1 при ошибке (устанавливая ERRNO с причиной) и (обычно) 0 при успехе. Если возвращаемое значение равно -1, эта карта типов возвращает undef. Если возвращаемое значение не равно -1, эта карта типов преобразует 0 (Perl false) в "0 но истина" (что является Perl true) или возвращает само значение, чтобы указать, что команда выполнилась успешно.

Модуль POSIX широко использует этот тип.

T_UV

Беззнаковое целое число.

T_IV

Знаковое целое число. Это приводится к требуемому целому типу при передаче в C и преобразуется в IV при возвращении в Perl.

T_INT

Знаковое целое число. Эта карта типов преобразует значение Perl в родной целочисленный тип (тип int на текущей платформе). При возвращении значения в Perl оно обрабатывается так же, как и для T_IV.

Её поведение идентично использованию типа int в XS с T_IV.

T_ENUM

Значение перечисления. Используется для передачи компонента перечисления из C. Нет причины передавать значение перечисления в C, поскольку оно хранится как IV внутри Perl.

T_BOOL

Тип булево. Это можно использовать для передачи значений true и false в C и из C.

T_U_INT

Это для беззнаковых целых чисел. Это эквивалентно использованию T_UV, но явно приводит переменную к типу unsigned int. По умолчанию тип unsigned int равен T_UV.

T_SHORT

Короткие целые числа. Это эквивалентно T_IV, но явно приводит возврат к типу short. По умолчанию карта типов short равна T_IV.

T_U_SHORT

Беззнаковые короткие целые числа. Это эквивалентно T_UV, но явно приводит возврат к типу unsigned short. По умолчанию карта типов unsigned short равна T_UV.

T_U_SHORT используется для типа U16 в стандартной карте типов.

T_LONG

Длинные целые числа. Это эквивалентно T_IV, но явно приводит возврат к типу long. По умолчанию карта типов long равна T_IV.

T_U_LONG

Беззнаковые длинные целые числа. Это эквивалентно T_UV, но явно приводит возврат к типу unsigned long. По умолчанию карта типов unsigned long равна T_UV.

T_U_LONG используется для типа U32 в стандартной карте типов.

T_CHAR

Одиночные символы 8-битной длины.

T_U_CHAR

Беззнаковый байт.

T_FLOAT

Число с плавающей точкой. Эта карта типов гарантирует возврат переменной, приведённой к типу float.

T_NV

Число с плавающей точкой Perl. Похож на T_IV и T_UV в том, что возвращаемый тип приводится к запрошенному числовому типу, а не к конкретному типу.

T_DOUBLE

Число с двойной точностью с плавающей точкой. Эта карта типов гарантирует возврат переменной, приведённой к типу double.

T_PV

Строка (char *).

T_PTR

Адрес памяти (указатель). Обычно ассоциируется с типом void *.

T_PTRREF

Аналогично T_PTR, за исключением того, что указатель хранится в скаляре, и ссылка на этот скаляр возвращается вызывающей стороне. Это можно использовать, чтобы скрыть фактическое значение указателя от программиста, так как обычно оно не требуется непосредственно внутри perl.

Карта типов проверяет, что ссылка на скаляр передаётся из Perl в XS.

T_PTROBJ

Аналогично T_PTRREF, за исключением того, что ссылка благословлена в класс. Это позволяет использовать указатель как объект. Чаще всего используется для работы со структурами C. Карта типов проверяет, что объект perl, переданный в процедуру XS, принадлежит к правильному классу (или является частью подкласса).

Указатель благословляется в класс, который является производным от имени типа указателя, но все '*' в имени заменены на 'Ptr'.

Только для XSUB DESTROY, T_PTROBJ оптимизирован до T_PTRREF. Это означает, что проверка класса пропущена.

T_REF_IV_REF

ЕЩЁ НЕТ

T_REF_IV_PTR

Похоже на T_PTROBJ в том, что указатель благословляется в скалярный объект. Разница заключается в том, что когда объект передаётся обратно в XS, он должен быть правильного типа (наследование не поддерживается), в то время как T_PTROBJ поддерживает наследование.

Указатель благословляется в класс, который является производным от имени типа указателя, но все '*' в имени заменены на 'Ptr'.

Только для XSUB DESTROY, T_REF_IV_PTR оптимизирован до T_PTRREF. Это означает, что проверка класса пропущена.

T_PTRDESC

ЕЩЁ НЕТ

T_REFREF

Аналогично T_PTRREF, за исключением того, что указатель, хранящийся в скаляре, на который ссылаются, де-ссылается и копируется в переменную вывода. Это означает, что T_REFREF относится к T_PTRREF так же, как T_OPAQUE к T_OPAQUEPTR. Всё ясно?

Реализована только часть ВВОДА этого (Perl в XSUB), и нет известных пользователей в ядре или на CPAN.

T_REFOBJ

Как T_REFREF, за исключением того, что выполняется строгая проверка типов (наследование не поддерживается).

Только для XSUB DESTROY T_REFOBJ оптимизирован до T_REFREF. Это означает, что проверка класса пропущена.

T_OPAQUEPTR

Это можно использовать для хранения байтов в строковом компоненте SV. Здесь представление данных не имеет значения для perl, и сами байты просто хранятся в SV. Предполагается, что переменная C является указателем (байты копируются из этой области памяти). Если указатель указывает на что-то, что представлено 8 байтами, то эти 8 байтов хранятся в SV (и length() сообщит значение 8). Этот элемент похож на T_OPAQUE.

В принципе, команда unpack() может использоваться для преобразования байтов обратно в число (если тип базового типа известен как число).

Этот элемент можно использовать для хранения структуры C (количество байтов, подлежащих копированию, вычисляется с помощью функции C sizeof ) и может использоваться как альтернатива T_PTRREF без необходимости беспокоиться о утечке памяти (так как Perl очистит SV).

T_OPAQUE

Это можно использовать для хранения данных из типов, не являющихся указателями, в строковой части SV. Это похоже на T_OPAQUEPTR, за исключением того, что карта типов извлекает указатель непосредственно, а не предполагает его предоставление. Например, если целое число импортируется в Perl с помощью T_OPAQUE вместо T_IV, то подлежащие байты, представляющие целое число, будут храниться в SV, но фактическое значение целого числа не будет доступно. Т.е. данные неявны для perl.

Данные можно извлечь, используя функцию unpack , если базовый тип потока байтов известен.

T_OPAQUE поддерживает ввод и вывод простых типов. T_OPAQUEPTR можно использовать для передачи этих байтов обратно в C, если указатель приемлем.

Неявный массив

xsubpp поддерживает специальный синтаксис для возврата упакованных массивов C в Perl. Если тип возврата XS указан как

array(type, nelem)

xsubpp скопирует содержимое nelem * sizeof(type) байтов из RETVAL в SV и поместит его в стек. Это действительно полезно только если количество возвращаемых элементов известно на этапе компиляции и вы не против иметь строку байтов в вашем SV. Используйте T_ARRAY для помещения переменного количества аргументов в стек возврата (хотя они не будут упакованы как единственная строка).

Это аналогично использованию T_OPAQUEPTR, но можно обработать более одного элемента.

T_PACKED

Вызывает функции, заданные пользователем, для преобразования. Для OUTPUT (XSUB в Perl), вызывается функция с именем XS_pack_$ntype со скаляром Perl вывода и C переменной, из которой нужно преобразовать. $ntype — это нормализованный тип C, который должен быть сопоставлен с Perl. Нормализация означает, что все * заменяются строкой Ptr. Значение возврата функции игнорируется.

Обратно, для сопоставления INPUT (Perl в XSUB), вызывается функция с именем XS_unpack_$ntype со входным скаляром Perl в качестве аргумента, и возвращаемое значение приводится к сопоставленному типу C и присваивается выходной переменной C.

Пример функции преобразования для структуры типа foo_t * может быть таким:

static void
XS_pack_foo_tPtr(SV *out, foo_t *in)
{
  dTHX; /* alas, signature does not include pTHX_ */
  HV* hash = newHV();
  hv_stores(hash, "int_member", newSViv(in->int_member));
  hv_stores(hash, "float_member", newSVnv(in->float_member));
  /* ... */

  /* mortalize as thy stack is not refcounted */
  sv_setsv(out, sv_2mortal(newRV_noinc((SV*)hash)));
}

Преобразование из Perl в C оставляется на усмотрение читателя, но прототип будет:

static foo_t *
XS_unpack_foo_tPtr(SV *in);

Вместо фактической функции C, которая должна извлекать контекст потока с помощью dTHX, вы можете определить макросы с тем же именем и избежать накладных расходов. Также имейте в виду возможность освобождения памяти, выделенной XS_unpack_foo_tPtr.

T_PACKEDARRAY

T_PACKEDARRAY подобен T_PACKED. Фактически, тип сопоставления INPUT (Perl в XSUB) идентичен, но тип сопоставления OUTPUT передает дополнительный аргумент функции XS_pack_$ntype. Этот третий параметр указывает количество элементов в выводе, чтобы функция могла корректно обрабатывать массивы C. Переменная должна быть объявлена пользователем и должна иметь имя count_$ntype, где $ntype — это нормализованное имя типа C, как объяснено выше. Подпись функции для примера выше и foo_t ** будет такой:

static void
XS_pack_foo_tPtrPtr(SV *out, foo_t *in, UV count_foo_tPtrPtr);

Тип третьего параметра произвольный, с точки зрения типа сопоставления. Он просто должен соответствовать объявленной переменной.

Конечно, если вы не знаете количество элементов в массиве C sometype **, в вашем XSUB, значение возврата из foo_t ** XS_unpack_foo_tPtrPtr(...) будет трудно понять. Поскольку детали полностью зависят от автора XS (пользователя типа сопоставления), существует несколько решений, ни одно из которых не является особенно элегантным. Наиболее распространенным решением было выделение памяти для N+1 указателей и назначение NULL (N+1)-му для облегчения итерации.

В качестве альтернативы, вероятно, предпочтительнее использовать настроенный тип сопоставления для ваших целей с самого начала.

T_DATAUNIT

ЕЩЁ НЕ ГОТОВО

T_CALLBACK

ЕЩЁ НЕ ГОТОВО

T_ARRAY

Используется для преобразования списка аргументов Perl в массив C и для помещения содержимого массива C в стек аргументов Perl.

Обычная сигнатура вызова:

@out = array_func( @in );

В списке может быть любое количество аргументов перед массивом, но входной и выходной массивы должны быть последними элементами списка.

При использовании для передачи списка Perl в C, автор XS должен предоставить функцию (названную по типу массива, но с заменой '*' на 'Ptr'), чтобы выделить память, необходимую для хранения списка. Должен возвращаться указатель. Автор XS отвечает за освобождение памяти при выходе из функции. Переменная ix_$var устанавливается в количество элементов в новом массиве.

При возвращении массива C в Perl, автор XS должен предоставить целочисленную переменную, называемую size_$var, содержащую количество элементов в массиве. Это используется для определения количества элементов, которые должны быть помещены в стек возвращаемых аргументов. Это не требуется на входе, так как Perl знает количество аргументов в стеке, когда вызывается процедура. Обычно эта переменная называлась бы size_RETVAL.

Кроме того, тип каждого элемента определяется по типу массива. Если массив использует тип intArray *, xsubpp автоматически определит, что он содержит переменные типа int, и воспользуется этим элементом сопоставления для копирования каждого элемента. Все метки '*' и 'Array' удаляются из имени для определения подтипа.

T_STDIO

Используется для передачи дескрипторов файлов Perl в C и из C, используя структуры FILE *.

T_INOUT

Используется для передачи дескрипторов файлов Perl в C и из C, используя структуры PerlIO * . Дескриптор файла может использоваться для чтения и записи. Соответствует режиму +<, см. также T_IN и T_OUT.

Для получения дополнительной информации об уровне абстракции ввода-вывода Perl см. perliol. Perl должен быть скомпилирован с -Duseperlio.

Нет проверки, чтобы гарантировать, что дескриптор файла, переданный из Perl в C, был создан с правильным режимом open().

Подсказка: учебник perlxstut хорошо описывает типы XS T_INOUT, T_IN и T_OUT.

T_IN

То же, что и T_INOUT, но дескриптор файла, возвращаемый из C в Perl, может использоваться только для чтения (режим <).

T_OUT

То же, что и T_INOUT, но дескриптор файла, возвращаемый из C в Perl, настроен на использование режима открытия +>.

© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.30.3/perlxstypemap

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API