perlxstypemap
СОДЕРЖАНИЕ
ИМЯ
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) идентичен, но typemapOUTPUTпередает дополнительный аргумент функции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