-
-
Notifications
You must be signed in to change notification settings - Fork 17
ffi #22
Description
probe for libffi and link to it if found. useffi, ffi_targets for the valid :nativconv() ABI args.
parse syntax:
use ffi; # NativeCall already taken and incompatible
extern sub NAME SIG ATTRIB?;
#or
sub NAME SIG :native() ATTRIB?;
The alternative for extern
is the perl6-style :native
attribute, with optional
arg :native("libname")
and optional :symbol("c_name")
.
Str arg or return types can have optional :encoded('utf8')
attributes.
The default return type is :void
(not :Int).
See https://docs.perl6.org/language/nativecall
Resolve the attribute arguments, safely. See #291. (Not as in Attribute::Handlers)
Use a new op dlcall/enterffi for it, instead of entersub. leaveffi not needed, as no blocks are stored for extern subs, just the call and the sigop. the sigop holds the info for argument and returntype translations, the callop does the translation, call, translation.
Without a :native(libname) the symbol searched in all loaded shared libraries.
So you can preload shared libs via the DynaLoader.
Add and separate a function to DynaLoad a pure shared library, without xs bootstrap, so extern does not need any library name. Other languages do it eg. with use lib ("mysqlclient.so");
Translate args in the optimizer to such a sub, upgrade to native.
Enforce native types for the sub parameters, resp. provide casts (unbox).
ditto for the return value.
A CvEXTERN(cv) needs a temp. libptr for the loaded shared lib (shared with the ffi cif), and an optional PV for the symbolname.
(mangled or unmangled, :symbol() override, _
prefix or not).
It doesn't need a CvSTART, nor a CvROOT, so overload those two.
At runtime libffi needs the XSUB address, and the cif, i.e. the ffi signature.
The symbolname is resolved to the XSUB address via DynaLoader, the sig is converted to a cif at compile-time.
We need a few more Configure probes and keys: useffi (to disable it), d_libffi (if the definition probed ok), i_ffi (if to include <ffi.h>), i_alloca (if to include alloca.h), d_alloca or d__alloca (for fast arg preperation).
Note that Larry had this in his TODO, but p5p removed it later.
Est. 2w
Architecture
parser: extern sub name (sig) :native() :symbol() :nativconv() :encoded();
- sig is stored as sigop attached to the CvEXTERN sub, not in the block (CvROOT). needed for prep_cif.
- attrs store the lib and symname in xsutils,
- NY: add the runtime attributes->import call to the stmt list there. compile-time works fine.
attributes::import (either compile-time or run-time):
- resolve the lib and name via DynaLoader (i.e. not in miniperl). See Resolve core attribute arguments, runtime setters, safely #291 for run-time attrs support :native($libname).
- set libhandle (temp. CvFFILIB) via dl_load_file
- resolve symbol ptr via dl_find_symbol
- store ptr at CvXFFI(). CvFFILIB is now unneeded, and re-used for the cif.
- ffi_prep_cif: prepare sig arity and type translations.
- set CvFFILIB from lib handle to cif.
- store the optional :symbol() override as proto (shared pvn). protos are not needed, a sig is mandatory.
compiler:
- ck_entersub_args_proto_or_list checks for CvEXTERN
- sets op from ENTERSUB to ENTERFFI (as with ENTERXSSUB)
- type check the call args
runtime: pp_enterffi
- prep_sig: copy and type-check args from perl stack to arg_values[] via sigop aux info.
ffi_call(cif, CvXFFI(cv), &rvalue, argvalues);
- prep_ret: copy rvalue to perl stack.