The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

XS::TCC - Embed, wrap & compile C code in Perl without going to disk

SYNOPSIS

use XS::TCC qw(tcc_inline);

tcc_inline q{
  int foo(int bar) {
    return bar * 2;
  }
};

print foo(3), "\n"; # prints 6
# more elaborate functions involving Perl types work as well

DESCRIPTION

Before you consider adopting this module, please have a look at the C::Blocks module. C::Blocks is a more powerful, more lovingly maintained piece of software. Due to current (as of early 2017) scarcity of spare time on my part, you can't expect to get a lot of support for XS::TCC from me. This being said, XS::TCC should work reliably at least on reasonably standard Linux systems. --Steffen

XS::TCC allows you to embed C code into your Perl that is compiled and linked on the fly, in memory, without ever touching your disk except to read the Perl code in the first place. This amazing feat actually has very little to do with this module's code but rather with TCC (TinyCC, see tinycc.org) which allows compilation and linking in memory.

On my first-gen core i5 laptop, making two small-medium size functions available to Perl takes around 30ms including parse, wrapper code generation, typemapping, compilation, linking, and XSUB installation. Wrapping more code is bound to be relatively faster.

The output of TCC is slower than the equivalent function compiled with GCC, but both beat regular Perl by a wide margin {citation required}.

FUNCTIONS

tcc_inline

The optionally exported tcc_inline function is the main end user interface for XS::TCC. In its simplest form, it simply takes a string of C code as its first parameter. The C code will be compiled with TCC on the fly (and in memory rather than on disk as with Inline), and any C functions in that string will be bound under the same name as XS functions. The argument and return types will be mapped with Perl's standard typemap functionality, see also the perlxstypemap man page.

Optionally, you can provide named parameters to tcc_inline as key-value pairs preceding the code string:

tcc_inline(
  option => 'value',
  option2 => 'value2',
  q{ int foo() {return 42;} }
);

Valid options are:

package

The Perl package to put the XS functions into instead of your current package.

typemap

The value for this option can be either a string of typemap code (ie. what you would put in a TYPEMAP block in XS or a typemap file in a Perl XS distribution) or an ExtUtils::Typemap object.

In either case, the given typemap will be merged with the core perl typemaps (your custom ones will supercede the core ones where applicable) and the resulting merged typemap will be used for the compilation.

ccopts

Any compiler flags you want to pass. By default, XS::TCC will use ExtUtils::Embed to intuit your CC options. If you pass a ccopts value, those options will replace the default options from ExtUtils::Embed::ccopts.

add_files

Can be a single path/file name or an array ref containing one or multiple. These additional C code-containing files will be passed to TCC to compile.

They will NOT be parsed for function signatures by XS::TCC. That is to say, functions in these files will NOT be exposed as XSUBs.

code

The C code to compile. You can use this form instead of the trailing code string. (But not both.)

warn_code

Debugging: If this is set to a true value, the generated XS code will be passed to warn before compiling it.

ADVANCED NOTES

This is a very incomplete section with notes on advanced usage.

Perl Context

In XS, it's very common to pass a pointer to the currently active Perl interpreter, also known as THX around. Many Perl API functions need to have such a context around to function properly. For convenience, one can find the currently active Perl interpreter without passing it around as a function parameter, but this comes at the cost of performance.

XS::TCC allows you to include the standard pTHX and pTHX_ macros in your function signatures to get the Perl context as an argument in your C function. To wit, the following to functions are equivalent in that they return the type of context that the function is called in (as the Perl internal integer ids corresponding to void/scalar/list contexts). This is a very useless thing to do, of course, this is for demonstration purposes only):

/* efficient */
int which_context(pTHX) {
  return (int)GIMME_V;
}

/* less efficient */
int which_context_slow() {
  dTHX;
  return (int)GIMME_V;
}

Testing this with a simple script gives on a threaded perl:

$ perl -Mblib author_tools/dthx_benchmark.pl 
                Rate  pTHX   dTHX
pTHX  1860.2+-0.31/s    -- -12.5%
dTHX 2124.91+-0.14/s 14.2%     --

On a perl compiled without multi-threading support, the timings are equal between the two variants.

SEE ALSO

AUTHOR

Steffen Mueller <smueller@cpan.org>

With much appreciated contributions from:

Tokuhiro Matsuno

David Mertens

COPYRIGHT AND LICENSE

Copyright (C) 2013, 2014, 2016, 2017 by Steffen Mueller

XS::TCC is distributed under the GNU Lesser General Public License
(see COPYING file).