The worst Perl API's

Perl usually has a pretty and wellthought API and tools to maintain it.

But of cause there is also a hall of shame in some old dirty corners, nobody ever uses.

No.1 B.xs: make_warnings_object

In order to provide Perl read-access to lexical warnings some fake SV is passed to B, created internally by make_warnings_object(). A warning is basically a short integer between 1-6, and lexical warnings are integers > 6 checked by bitmasks e.g. see warnings.pm.

The C API is SV* until 5.8.9 and since 5.10 STRLEN*, which is basically a int*.

Since 5.8.9 and 5.9.4 WARN objects are PV's ("strings"), because it's natural to represent a ptr as RV to IV ("intref") as with < 5.8.9, or as PV pointer. However due to a bug I don't care to be fixed, the integer value is the length of the string provided as PVX, and the string itself is some random value. So to read such a B::SV object for lexical warnings you read now the length of the $sv->PVX.

You decode such a SV with:

my $warn = $] >= 5.008009 ? length($sv->PVX) : $sv->IV;

A normal API would just pass the IV value to B, not even a full SV. Or a B::SPECIAL object as it is done for non-lexical warnings. But leaving a IV as before would have also been fine.

No.2 XSLoader files

XSLoader is the easier interface to load dynamic Perl modules. Compared to DynaLoader. It's so easy that there's even no function to accept the dynamic library to be loaded. It's entirely context dependent, it only takes this filename from the context of the call. So if you need to load dynamic XS modules from the Perl C API, you need to first set the CopFILE ptr of the previous nextstate cop to the path of the dynamic library, and then you call XSLoader::Load.

 CopFILE_set(cxstack[0].blk_oldcop, "$xspath");
 call_pv("XSLoader::load", G_VOID|G_DISCARD);

A normal API would provide e.g.

 XPUSHp("$xspath");
 call_pv("XSLoader::load", G_VOID|G_DISCARD);

That means XSLoader::load($filename) within Perl.

2 Comments

XSLoader is a simple wrapper around DynaLoader. If you want something that isn't simple, you should be using DynaLoader instead. What you're describing is using the wrong tool for the job…

About Reini Urban

user-pic Working at cPanel on cperl, B::C (the perl-compiler), parrot, B::Generate, cygwin perl and more guts, keeping the system alive.