Peta::FFI#
Call C library functions from Perl with no build step and no binding crate.
Peta::FFI is the dynamic FFI layer pperl ships for reaching into shared libraries at runtime. You open a library with dlopen, call any of its exported functions through call by giving a type signature string, and release the handle with dlclose. A fourth helper, scan, enumerates the shared libraries the dynamic linker already knows about, which is useful for finding the right soname before you open it.
This is how Perl code here reaches a C library: pperl loads no compiled extension modules, so anything living in a .so is called either through this module or through one of the pre-baked wrappers built on it.
Reach for it when:
The function you need lives in a system library (
libm,libc,libuuid,libcrypto).You already know the C prototype and want a one-liner, not a build step.
You are calling into a third-party
.sothat no pre-baked wrapper covers.
C calling back into Perl is supported: closure wraps a coderef as a function pointer you can hand to any C API that wants one (see the Callbacks category).
Everything crossing the boundary is a scalar - integer, float, string or raw address - as the type-code table below spells out. Two things are therefore outside what this module can express, and pperl offers no other route to them: a C function that takes or returns a struct by value, and deriving types from a header. A struct reached through a pointer is workable with the o type code and the memory primitives, but you supply the field offsets yourself; and you always read the C prototype and write the matching signature by hand, since a signature that disagrees with the real prototype is undefined behaviour rather than an error.
The two sibling modules Peta::FFI::Libc and Peta::FFI::UUID are pre-baked convenience wrappers built on top of this layer - they handle the dlopen / call / dlclose dance for you for a fixed set of functions. If your need is covered by one of them, prefer it over hand-rolled FFI.
Signature strings#
Every call takes a signature string of the form (args)ret, where each position is one single-character type code:
Code | C type | Perl side |
|---|---|---|
|
| return only; |
|
| integer |
|
| integer |
|
| integer |
|
| float |
|
| float |
|
| input string |
| mutable buffer | output buffer, auto-allocated |
| opaque pointer | raw address as integer |
A signature with no arguments is written ()ret, e.g. ()i for an int-returning no-arg function. P allocates a zeroed buffer big enough for the passed scalar and hands the pointer to the callee - typical use is for functions like uuid_generate that write into a caller-supplied buffer.
o is the handle type for C APIs built on opaque structs (PGconn*, sqlite3*, MYSQL*): the raw address travels as a Perl integer, is never dereferenced by the runtime, and undef/0 passes NULL. Never use p for such pointers - p returns copy-until-NUL string semantics, which is wrong and unsafe for non-string data.
Memory primitives#
For C APIs that traffic in caller-owned memory (out-parameters, pointer arrays, length-counted buffers) the module provides the pointer toolbox: alloc/free, peek/peek_cstr, poke, and pack_ptr/unpack_ptr. Addresses are ordinary Perl integers as with o. A pointer array (e.g. char *argv[]) is built portably as join "", map pack_ptr($_), @addrs poked into an alloced block, or passed directly as a p string when the callee only reads it during the call.
Synopsis#
use Peta::FFI;
my $libm = Peta::FFI::dlopen("libm.so.6");
my $root = Peta::FFI::call($libm, "sqrt", "(d)d", 2.0);
Peta::FFI::dlclose($libm);
print $root, "\n"; # 1.4142135623731
Modules#
Peta::FFI::Libc- Call common libc functions from Perl without writing a single line of FFI glue.Peta::FFI::UUID- Generate and parse RFC 4122 UUIDs via the system’s libuuid library.
Functions#
Library loading#
dlopen#
Open a shared library and return a handle suitable for passing to call.
dlclose#
Release a library handle previously returned by dlopen.
Function calls#
call#
Invoke a C function from an opened library and return its result.
Symbol introspection#
scan#
List the shared libraries the dynamic linker already knows about.
Callbacks#
closure#
Wrap a Perl coderef as a C-callable function pointer.
closure_free#
Release a closure created by closure.
Memory#
peek#
Read $len raw bytes at address $ptr into a Perl byte string.
peek_cstr#
Read the NUL-terminated C string at address $ptr.
poke#
Copy a Perl byte string into memory at address $ptr.
alloc#
Allocate $len zeroed bytes of C memory; returns the address.
free#
Release memory obtained from alloc.
pack_ptr#
Pack an address into a native pointer-sized byte string.
unpack_ptr#
Unpack a native pointer-sized byte string into an address.