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 на строке следующим образом. Пример из файла core 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, уже доступны. Кроме того, основной typemap содержит значения XS по умолчанию для большого числа типов C. Например, если вы просто вернёте char * из своей XSUB, основной typemap свяжет этот тип C с типом T_PV XS. Это означает, что ваша строка 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.
Обратите внимание, что эта таблица типов не уменьшает счётчик ссылок при возвращении ссылки на SV*. См. также: T_SVREF_REFCOUNT_FIXED
- T_SVREF_FIXED
-
Используется для передачи ссылки на SV и возврата ссылки на 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 false) в "0 but true" (что является 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-структурами. Таблица типов проверяет, что переданный в процедуру XS perl-объект принадлежит правильному классу (или является частью подкласса).
Указатель благословляется в класс, производный от имени типа указателя, но со всеми '*' в имени, заменёнными на '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 to XSUB) typemap идентичен, ноOUTPUTtypemap передает дополнительный аргумент функции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.Для получения дополнительной информации об абстракции ввода-вывода 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–2023 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.38.0/perlxstypemap