PERLXSTYPEMAP(1perl)

๐Ÿ“ฆ
version 5.44.0 ยท 2 versions
, in arch rolling

โœจ PERLXSTYPEMAP โœจ โ€” the 1perl glow-up (Perl Programmers Reference Guide era, bestie)

okay so. this is perlxstypemap, the page that explains how Perl XS maps C types to Perl types and back again, and honestly it's giving backstage pass to the whole XS operation. ๐Ÿ’…


๐ŸŒธ NAME ๐ŸŒธ

perlxstypemap โ€” Perl XS C/Perl type mapping. that's it. that's the name. iconic.


๐Ÿ’– DESCRIPTION ๐Ÿ’–

ngl, the more you sit with the idea of making two languages talk to each other, the more you clock that most of the programmer effort goes into converting between the data structures that are native to each language. it EATS the time. this absolutely trumps other stuff like differing calling conventions, because the problem space is just so much bigger. fr fr โ€” there are simply more ways to shove data into memory than there are ways to implement a function call. ๐Ÿ˜ญ

Perl XS' attempt at solving this is the whole concept of typemaps. at an abstract level, a Perl XS typemap is nothing but a recipe for converting from a certain Perl data structure to a certain C data structure and vice versa. since there can be C types that are sufficiently similar to one another to warrant converting with the same logic, XS typemaps are represented by a unique identifier, henceforth called an XS type in this document. you can then tell the XS compiler that multiple C types are to be mapped with the same XS typemap. slay. ๐ŸŽ€

in your XS code, when you define an argument with a C type, or when you're using a CODE: and an OUTPUT: section together with a C return type of your XSUB, it'll be the typemapping mechanism that makes this easy. main character energy honestly.

๐Ÿฆ‹ Anatomy of a typemap ๐Ÿฆ‹

more practically: the typemap is a collection of code fragments which are used by the xsubpp compiler to map C function parameters and values to Perl values. the typemap file may consist of three sections labelled TYPEMAP, INPUT, and OUTPUT.

  • an unlabelled initial section is assumed to be a TYPEMAP section.
  • the INPUT section tells the compiler how to translate Perl values into variables of certain C types.
  • the OUTPUT section tells the compiler how to translate the values from certain C types into values Perl can understand.
  • the TYPEMAP section tells the compiler which of the INPUT and OUTPUT code fragments should be used to map a given C type to a Perl value.

the section labels TYPEMAP, INPUT, or OUTPUT must begin in the first column on a line by themselves, and must be in uppercase. no cap, that part is strict.

each type of section can appear an arbitrary number of times and doesn't have to appear at all. for example, a typemap may commonly lack INPUT and OUTPUT sections if all it needs to do is associate additional C types with core XS types like T_PTROBJ. lines that start with a hash # are considered comments and ignored in the TYPEMAP section, but are considered significant in INPUT and OUTPUT. blank lines are generally ignored.

traditionally, typemaps needed to be written to a separate file, conventionally called typemap in a CPAN distribution. with ExtUtils::ParseXS (the XS compiler) version 3.12 or better which comes with perl 5.16, typemaps can also be embedded directly into XS code using a HERE-doc like syntax:

  TYPEMAP: <<HERE
  ...
  HERE

where HERE can be replaced by other identifiers like with normal Perl HERE-docs. all details below about the typemap textual format remain valid. ๐Ÿ’ฏ

the TYPEMAP section should contain one pair of C type and XS type per line as follows. an example from the core typemap file:

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

the INPUT and OUTPUT sections have identical formats, that is, each unindented line starts a new in- or output map respectively. a new in- or output map must start with the name of the XS type to map on a line by itself, followed by the code that implements it indented on the following lines. example:

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

we'll get to the meaning of those Perlish-looking variables in a little bit. promise. ๐Ÿ™ˆ

finally, here's an example of a full typemap file for mapping C strings of the char * type to Perl scalars/strings:

  TYPEMAP
  char *  T_PV

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

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

here's a more complicated example: suppose that you wanted struct netconfig to be blessed into the class Net::Config. one way to do this is to use underscores (_) to separate package names, as follows:

  typedef struct netconfig * Net_Config;

and then provide a typemap entry T_PTROBJ_SPECIAL that maps underscores to double-colons (::), and declare Net_Config to be of that type:

  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);

the INPUT and OUTPUT sections substitute underscores for double-colons on the fly, giving the desired effect. this example demonstrates some of the power and versatility of the typemap facility. it ate, honestly. ๐Ÿ”ฅ

the INT2PTR macro (defined in perl.h) casts an integer to a pointer of a given type, taking care of the possible different size of integers and pointers. there are also PTR2IV, PTR2UV, PTR2NV macros, to map the other way, which may be useful in OUTPUT sections. ๐Ÿซถ

๐Ÿ’œ The Role of the typemap File in Your Distribution ๐Ÿ’œ

the default typemap in the lib/ExtUtils directory of the Perl source contains many useful types which can be used by Perl extensions. some extensions define additional typemaps which they keep in their own directory. these additional typemaps may reference INPUT and OUTPUT maps in the main typemap. the xsubpp compiler will allow the extension's own typemap to override any mappings which are in the default typemap. instead of using an additional typemap file, typemaps may be embedded verbatim in XS with a heredoc-like syntax. see the documentation on the TYPEMAP: XS keyword.

for CPAN distributions, you can assume that the XS types defined by the perl core are already available. additionally, the core typemap has default XS types for a large number of C types. for example, if you simply return a char * from your XSUB, the core typemap will have this C type associated with the T_PV XS type. that means your C string will be copied into the PV (pointer value) slot of a new scalar that will be returned from your XSUB to Perl. cute little handoff. ๐ŸŒธ

if you're developing a CPAN distribution using XS, you may add your own file called typemap to the distribution. that file may contain typemaps that either map types that are specific to your code, or that override the core typemap file's mappings for common C types.

๐ŸŒˆ Sharing typemaps Between CPAN Distributions ๐ŸŒˆ

starting with ExtUtils::ParseXS version 3.13_01 (comes with perl 5.16 and better), it is rather easy to share typemap code between multiple CPAN distributions. the general idea is to share it as a module that offers a certain API, and have the dependent modules declare that as a build-time requirement and import the typemap into the XS. an example of such a typemap-sharing module on CPAN is ExtUtils::Typemaps::Basic.

two steps to getting that module's typemaps available in your code:

  • declare ExtUtils::Typemaps::Basic as a build-time dependency in Makefile.PL (use BUILD_REQUIRES), or in your Build.PL (use build_requires).
  • include the following line in the XS section of your XS file: (don't break the line)
    INCLUDE_COMMAND: $^X -MExtUtils::Typemaps::Cmd
                     -e "print embeddable_typemap(q{Basic})"

๐Ÿงš Writing typemap Entries ๐Ÿงš

each INPUT or OUTPUT typemap entry is a double-quoted Perl string that will be evaluated in the presence of certain variables to get the final C code for mapping a certain C type.

this means you can embed Perl code in your typemap (C) code using constructs such as ${ perl code that evaluates to scalar reference here }. a common use case is to generate error messages that refer to the true function name even when using the ALIAS XS feature:

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

for many typemap examples, refer to the core typemap file that can be found in the perl source tree at lib/ExtUtils/typemap.

the Perl variables that are available for interpolation into typemaps are the following:

  • $var โ€” the name of the input or output variable, eg. RETVAL for return values.
  • $type โ€” the raw C type of the parameter, any : replaced with _. e.g. for a type of Foo::Bar, $type is Foo__Bar
  • $ntype โ€” the supplied type with * replaced with Ptr. e.g. for a type of Foo*, $ntype is FooPtr
  • $arg โ€” the stack entry, that the parameter is input from or output to, e.g. ST(0)
  • $argoff โ€” the argument stack offset of the argument. ie. 0 for the first argument, etc.
  • $pname โ€” the full name of the XSUB, with including the PACKAGE name, with any PREFIX stripped. this is the non-ALIAS name.
  • $Package โ€” the package specified by the most recent PACKAGE keyword.
  • $ALIAS โ€” non-zero if the current XSUB has any aliases declared with ALIAS.

๐Ÿ‘‘ Full Listing of Core Typemaps ๐Ÿ‘‘

each C type is represented by an entry in the typemap file that is responsible for converting perl variables (SV, AV, HV, CV, etc.) to and from that type. the following sections list all XS types that come with perl by default. buckle up bestie, it's a whole roster. โญ

๐Ÿ’– T_SV ๐Ÿ’–

this simply passes the C representation of the Perl variable (an SV*) in and out of the XS layer. this can be used if the C code wants to deal directly with the Perl variable.

๐Ÿ’– T_SVREF ๐Ÿ’–

used to pass in and return a reference to an SV.

note that this typemap does not decrement the reference count when returning the reference to an SV*. see also: T_SVREF_REFCOUNT_FIXED

๐Ÿ’– T_SVREF_REFCOUNT_FIXED ๐Ÿ’–

used to pass in and return a reference to an SV. this is a fixed variant of T_SVREF that decrements the refcount appropriately when returning a reference to an SV*. introduced in perl 5.15.4.

๐Ÿ’– T_AVREF ๐Ÿ’–

from the perl level this is a reference to a perl array. from the C level this is a pointer to an AV.

note that this typemap does not decrement the reference count when returning an AV*. see also: T_AVREF_REFCOUNT_FIXED

T_AVREF_REFCOUNT_FIXED ๐Ÿ’œ

okay so from the perl level this is literally just a reference to a perl array. From the C level it's a pointer to an AV. And here's the tea: this is the fixed variant of T_AVREF โ€” the glow-up is that it decrements the refcount appropriately when returning an AV*. ๐Ÿซถ Introduced in perl 5.15.4.


T_HVREF ๐Ÿ“

From the perl level this is a reference to a perl hash. From the C level it's a pointer to an HV. cute, right? standard. slay.

โš ๏ธ but bestie, mind this: this typemap does not decrement the reference count when returning an HV*. That's the whole reason the refcount-fixed version exists. See also: T_HVREF_REFCOUNT_FIXED ๐Ÿ‘€

T_HVREF_REFCOUNT_FIXED โœจ

From the perl level this is a reference to a perl hash. From the C level it's a pointer to an HV. This is the fixed variant of T_HVREF that decrements the refcount appropriately when returning an HV*. no more leaky leaks, we love to see it. ๐Ÿ’… Introduced in perl 5.15.4.


T_CVREF ๐ŸŽ€

From the perl level this is a reference to a perl subroutine, like $sub = sub { 1 }; (<- yes, exactly that). From the C level it's a pointer to a CV.

โš ๏ธ and fr fr, same warning as above: this typemap does not decrement the reference count when returning an HV*. See also: T_HVREF_REFCOUNT_FIXED.

T_CVREF_REFCOUNT_FIXED ๐ŸŒธ

From the perl level this is a reference to a perl subroutine (e.g. $sub = sub { 1 };). From the C level it's a pointer to a CV.

This is a fixed variant of T_HVREF that decrements the refcount appropriately when returning an HV*. ๐Ÿ‘‘ Introduced in perl 5.15.4.


T_SYSRET ๐Ÿ”ฅ

The T_SYSRET typemap is what you use to process return values from system calls. It's only meaningful when you're passing values from C to perl โ€” there's genuinely no concept of passing a system return value from Perl to C. nope. doesn't exist. ๐Ÿ™…

Here's the vibe: system calls return -1 on error (and they set ERRNO with the reason, iconic of them) and (usually) 0 on success.

  • If the return value is -1, this typemap returns undef.
  • If the return value is not -1, this typemap translates a 0 (which is perl false, booo) into "0 but true" (which is perl true, yay โœจ) โ€” or else it just returns the value itself, to signal that the command succeeded.

The POSIX module makes extensive use of this type. it's basically its whole personality. ๐Ÿ’–


T_UV โญ

An unsigned integer. that's it. that's the whole thing. periodt.

T_IV ๐ŸŒˆ

A signed integer. This one gets cast to the required integer type when you pass it to C, and converted to an IV when it comes back to Perl.

T_INT ๐Ÿฆ‹

A signed integer. This typemap converts the Perl value to a native integer type (aka the int type on whatever platform you're on). When returning the value to perl it's processed in exactly the same way as for T_IV.

Its behaviour is identical to using an int type in XS with T_IV. twin behaviour, no notes.

T_ENUM ๐Ÿ’œ

An enum value. Used to transfer an enum component from C.

heads up: there is no reason to pass an enum value to C, since it's stored as an IV inside perl anyway.

T_BOOL โœจ

A boolean type. This can be used to pass true and false values to and from C. true, false, we simply love both. ๐Ÿซถ

T_U_INT ๐Ÿ“

This is for unsigned integers. It's equivalent to using T_UV, except it explicitly casts the variable to type unsigned int. And btw, the default type for unsigned int is T_UV.

T_SHORT ๐ŸŽ€

Short integers. Equivalent to T_IV, but it explicitly casts the return to type short. The default typemap for short is T_IV.

T_U_SHORT ๐ŸŒธ

Unsigned short integers. Equivalent to T_UV, but it explicitly casts the return to type unsigned short. The default typemap for unsigned short is T_UV.

T_U_SHORT is used for type U16 in the standard typemap.

T_LONG ๐Ÿ”ฅ

Long integers. Equivalent to T_IV, but it explicitly casts the return to type long. The default typemap for long is T_IV.

T_U_LONG โญ

Unsigned long integers. Equivalent to T_UV, but it explicitly casts the return to type unsigned long. The default typemap for unsigned long is T_UV.

T_U_LONG is used for type U32 in the standard typemap.

T_CHAR ๐ŸŒˆ

Single 8-bit characters. teeny tiny. adorable. ๐Ÿฆ‹

T_U_CHAR ๐Ÿ’…

An unsigned byte.

T_FLOAT ๐Ÿ“

A floating point number. This typemap guarantees to return a variable cast to a float. no cap.

T_NV โœจ

A Perl floating point number. Similar to T_IV and T_UV in that the return type gets cast to the requested numeric type rather than to some specific type. so flexible, so versatile, we stan. ๐Ÿ‘‘

T_DOUBLE ๐Ÿ’œ

A double precision floating point number. This typemap guarantees to return a variable cast to a double.

T_PV ๐ŸŽ€

A string (char *). yeah. that's it. ๐Ÿ’€

T_PTR ๐ŸŒธ

A memory address (pointer). Typically associated with a void * type.


T_PTRREF ๐Ÿฆ‹

Similar to T_PTR, except that the pointer gets stored in a scalar and the reference to that scalar is what's returned to the caller. This can be used to hide the actual pointer value from the programmer, since it's usually not required directly from within perl. sneaky, we love a secret. ๐Ÿคซ

The typemap checks that a scalar reference is passed from perl to XS. so bring the right type or don't come at all bestie. ๐Ÿ’…

T_PTROBJ ๐Ÿ”ฅ

Similar to T_PTRREF, except that the reference is blessed into a class. This lets the pointer be used as an object. Most commonly used to deal with C structs. The typemap checks that the perl object passed into the XS routine is of the correct class (or part of a subclass).

The pointer is blessed into a class that's derived from the name of the type of the pointer, but with all '*' in the name replaced with 'Ptr'. so foo* becomes fooPtr, iconic naming convention honestly. โญ

For "DESTROY" XSUBs only, a T_PTROBJ is optimized to a T_PTRREF. This means the class check is skipped. ๐Ÿ’€

T_REF_IV_REF ๐Ÿ’œ

NOT YET ๐Ÿ™ˆ

T_REF_IV_PTR ๐ŸŒˆ

Similar to T_PTROBJ in that the pointer is blessed into a scalar object. The difference is that when the object is passed back into XS it must be of the correct type โ€” inheritance is not supported here โ€” while T_PTROBJ does support inheritance. strict queen behaviour.

The pointer is blessed into a class that's derived from the name of the type of the pointer but with all '*' in the name replaced with 'Ptr'.

For "DESTROY" XSUBs only, a T_REF_IV_PTR is optimized to a T_PTRREF. This means the class check is skipped. ๐Ÿ’€

T_PTRDESC ๐Ÿ“

NOT YET ๐Ÿ™ˆ

T_REFREF ๐ŸŽ€

Similar to T_PTRREF, except the pointer stored in the referenced scalar gets dereferenced and copied to the output variable. Which basically means T_REFREF is to T_PTRREF as T_OPAQUE is to T_OPAQUEPTR. All clear? ๐Ÿ˜ญ

heads up: only the INPUT part of this is implemented (Perl to XSUB), and there are no known users in core or on CPAN. so... it's giving ghost town. ๐Ÿ‘ป

T_REFOBJ ๐ŸŒธ

Like T_REFREF, except it does strict type checking (and no, inheritance is not supported). no shortcuts, bestie.

For "DESTROY" XSUBs only, a T_REFOBJ is optimized to a T_REFREF. This means the class check is skipped. ๐Ÿ’€

T_OPAQUEPTR โœจ

This one can be used to store bytes in the string component of the SV. Here the representation of the data is irrelevant to perl and the bytes themselves just get stored in the SV. It's assumed that the C variable is a pointer (the bytes are copied from that memory location). If the pointer points to something represented by 8 bytes, then those 8 bytes get stored in the SV (and length() will report a value of 8). This entry is similar to T_OPAQUE.

In principle, the unpack() command can be used to convert the bytes back to a number (if the underlying type is known to be a number).

This entry can be used to store a C structure โ€” the number of bytes to be copied is calculated using the C sizeof function โ€” and it can be used as an alternative to T_PTRREF without having to worry about a memory leak, since Perl will clean up the SV for you. ๐Ÿซถ no leaky, only clean.

T_OPAQUE ๐Ÿ’œ

This one can be used to store data from non-pointer types in the string part of an SV. It's similar to T_OPAQUEPTR, except that the typemap retrieves the pointer directly rather than assuming it's being supplied.

For example: if an integer is imported into Perl using T_OPAQUE rather than T_IV, the underlying bytes representing the integer will be stored in the SV โ€” but the actual integer value will not be available. i.e. The data is opaque to perl. ๐Ÿ”ฎ can't see through it, no cap.

The data may be retrieved using the unpack function, if the underlying type of the byte stream is known.

T_OPAQUE supports input and output of simple types. T_OPAQUEPTR can be used to pass these bytes back into C if a pointer is acceptable. ๐Ÿ’…


Implicit array ๐ŸŒˆ

xsubpp supports a special syntax for returning packed C arrays to perl. If the XS return type is given as

array(type, nelem)

then xsubpp will copy the contents of nelem * sizeof(type) bytes from RETVAL to an SV and push it onto the stack. This is only really useful if the number of items to be returned is known at compile time and you don't mind having a string of bytes in your SV.

Use T_ARRAY if you want to push a variable number of arguments onto the return stack โ€” though heads up, they won't be packed as a single string. ๐Ÿ“ฆ

This is similar to using T_OPAQUEPTR but can be used to process more than one element. overachiever energy, honestly. โญ


T_PACKED ๐Ÿ”ฅ

This one calls user-supplied functions for conversion. For "OUTPUT" (XSUB to Perl), a function named XS_pack_$ntype is called with the output Perl scalar and the C variable to convert from. $ntype is the normalized C type that's being mapped to Perl. "Normalized" here means that all "*" get replaced by the string "Ptr". The return value of the function is ignored. bye, we don't care about it. ๐Ÿ™ˆ

Conversely, for "INPUT" (Perl to XSUB) mapping, the function named XS_unpack_$ntype is called with the input Perl scalar as its argument, and the return value is cast to the mapped C type and assigned to the output C variable.

An example conversion function for a typemapped struct foo_t * might be:

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)));
}

The conversion from Perl to C is left as an exercise to the reader ๐Ÿ˜ญ (yes, really, that's what it says), but the prototype would be:

static foo_t *
XS_unpack_foo_tPtr(SV *in);

Instead of writing an actual C function that has to fetch the thread context using dTHX, you can define macros of the same name and skip that overhead entirely. efficiency slay. โœจ

Also, keep in mind to possibly free the memory allocated by XS_unpack_foo_tPtr. ๐ŸŒธ

๐Ÿ’– T_PACKEDARRAY ๐Ÿ’–

okay so T_PACKEDARRAY is basically T_PACKED's cooler sibling โœจ The INPUT (Perl to XSUB) typemap is literally identical, no notes. BUT the OUTPUT typemap passes an extra argument to the XS_pack_$ntype function ๐Ÿ‘€

That third parameter tells the function how many elements are in the output, so it can handle C arrays sanely instead of just vibing into the void. And you โ€” yes you, bestie โ€” have to declare the variable yourself, and it must be named count_$ntype, where $ntype is the normalized C type name as explained above ๐Ÿซถ

So for the example above plus foo_t **, the signature would be:

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

ngl, the type of that third parameter is completely arbitrary as far as the typemap is concerned โ€” it just has to line up with the variable you declared. that's it, that's the rule ๐Ÿ’…

Of course, unless you know the number of elements in the sometype ** C array, within your XSUB, the return value from foo_t ** XS_unpack_foo_tPtrPtr(...) is gonna be hard to decipher ๐Ÿ˜ญ Since the details are all up to the XS author (that's the typemap user), there are several solutions, and none of them are particularly elegant. the most commonly seen solution has been to allocate memory for N+1 pointers and assign NULL to the (N+1)th one, so iteration is at least possible ๐Ÿ™ˆ

Alternatively, using a customized typemap for your purposes in the first place is probably preferable. lowkey the move.


๐ŸŒธ T_DATAUNIT ๐ŸŒธ

NOT YET

๐Ÿฆ‹ T_CALLBACK ๐Ÿฆ‹

NOT YET


โœจ T_ARRAY โœจ

This one converts the perl argument list to a C array, and it also pushes the contents of a C array back onto the perl argument stack. dual purpose, main character energy ๐Ÿ‘‘

The usual calling signature is:

@out = array_func( @in );

You can have any number of arguments in the list before the array, but the input and output arrays must be the last elements in the list. that's non-negotiable bestie ๐Ÿšซ

When it's used to pass a perl list to C, the XS writer must provide a function โ€” named after the array type but with Ptr substituted for * โ€” that allocates the memory required to hold the list. It should return a pointer. And it is up to the XS writer to free that memory when exiting the function, so like... don't forget, that's a leak and leaks are not cute ๐Ÿ’€ The variable ix_$var is set to the number of elements in the new array.

When returning a C array to Perl, the XS writer must provide an integer variable called size_$var containing the number of elements in the array. That's how it figures out how many elements get pushed onto the return argument stack. This isn't required on input, because Perl already knows how many arguments are on the stack when the routine is called ๐Ÿง  Ordinarily this variable would be called size_RETVAL.

Additionally, the type of each element is determined from the type of the array. If the array uses type intArray *, xsubpp will automatically work out that it contains variables of type int and use that typemap entry to do the copy of each element. All pointer * and Array tags are removed from the name to determine the subtype ๐Ÿ”


๐ŸŽ€ T_STDIO ๐ŸŽ€

This is used for passing perl filehandles to and from C using FILE * structures.

๐Ÿ’œ T_INOUT ๐Ÿ’œ

This is used for passing perl filehandles to and from C using PerlIO * structures. The file handle can be used for reading and writing. This corresponds to the +< mode โ€” see also T_IN and T_OUT ๐Ÿ”

See perliol for more information on the Perl IO abstraction layer. Perl must have been built with -Duseperlio.

There is no check to assert that the filehandle passed from Perl to C was created with the right open() mode. so like, be careful, okay? ๐Ÿ˜ญ

Hint: the perlxstut tutorial covers the T_INOUT, T_IN, and T_OUT XS types nicely ๐Ÿ’… go read it, you'll eat.

๐Ÿ“ T_IN ๐Ÿ“

Same as T_INOUT, but the filehandle that's returned from C to Perl can only be used for reading (mode <).

โญ T_OUT โญ

Same as T_INOUT, but the filehandle that's returned from C to Perl is set to use the open mode +>.


aaaand that's a wrap on perlxstypemap bestie, you made it to the end and honestly? iconic ๐Ÿ† this was PERLXSTYPEMAP(1perl) from perl v5.44.0, dated 2026-10-17 โ€” go forth and typemap, mwah ๐Ÿ’–โœจ๐Ÿซถ

๐Ÿ“ฆ where this page comes from
  • arch rolling: perl 5.44.0-1 ยท Artistic-1.0-Perl AND GPL-1.0-or-later
  • ๐Ÿ’– girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms