Spec-Zone.ru › Perl 5.36

perlxstypemap

СОДЕРЖАНИЕ

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

ИМЯ

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

ОПИСАНИЕ

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

Попытка Perl XS решить эту проблему заключается в концепции typemap. На абстрактном уровне typemap Perl XS – это просто рецепт для преобразования из определенной структуры данных 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 могут ссылаться на карты INPUT и OUTPUT в главном файле typemap. Компилятор xsubpp позволит typemap расширения переопределять любые сопоставления, которые находятся в файле typemap по умолчанию. Вместо использования дополнительного файла typemap, typemap можно вставить непосредственно в XS с помощью синтаксиса heredoc. См. документацию по ключевому слову TYPEMAP: XS.

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

Если вы разрабатываете дистрибутив CPAN с использованием XS, вы можете добавить свой собственный файл с именем typemap в дистрибутив. Этот файл может содержать typemap, которые либо сопоставляют типы, специфичные для вашего кода, либо переопределяют сопоставления файла core 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 обратитесь к файлу core 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

Это просто передаёт представление переменной Perl в C (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 = sub { 1 };). На уровне C это указатель на CV.

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

T_CVREF_REFCOUNT_FIXED

На уровне perl это ссылка на подпрограмму perl (например, $sub = 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 ложь) в "0, но истина" (что является perl истиной) или возвращает само значение, чтобы указать, что команда выполнилась успешно.

Модуль 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. На самом деле, typemap INPUT (Perl to XSUB) идентичен, но typemap 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);

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

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

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

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, и использует эту запись typemap для выполнения копии каждого элемента. Все теги указателей '*' и 'Array' удаляются из имени для определения подтипа.

T_STDIO

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

T_INOUT

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

См. perliol для получения дополнительной информации об абстракции ввода-вывода Perl. 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–2021 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.36.0/perlxstypemap

Spec-Zone.ru

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