Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Auto-FFI (Peta::FFI)

PetaPerl enthält eine eingebaute Foreign Function Interface, die es ermöglicht, C-Bibliotheksfunktionen direkt aus Perl aufzurufen — ohne XS zu schreiben, ohne C-Compiler, ohne jeglichen Build-Schritt. Dies ist eine PetaPerl-exklusive Funktion ohne perl5-Entsprechung.

Architektur

Das FFI-System besteht aus drei Schichten:

SchichtModulZweck
0Peta::FFIRohes FFI: dlopen + Aufruf mit Typsignaturen
1Peta::FFI::Libc, ::UUID, ::GMPFertige Bindings für bestimmte Bibliotheken
2Peta::FFI::scan()Erkennung: verfügbare Systembibliotheken auflisten

Schicht 0 verwendet libffi für den Dispatch — jede C-Funktionssignatur funktioniert, keine Code-Generierung erforderlich.

Schicht 0: Rohes FFI

dlopen / call / dlclose

use Peta::FFI qw(dlopen call dlclose);

my $lib = dlopen("libm.so.6");
my $result = call($lib, "sqrt", "(d)d", 2.0);   # √2 = 1.4142...
print "sqrt(2) = $result\n";
dlclose($lib);

Typsignatur-Format

Die Signaturzeichenkette "(arg_types)return_type" verwendet einstellige Typcodes:

CodeC-TypPerl-Zuordnung
vvoid(kein Wert)
iintIV
llongIV
Lunsigned long / size_tUV
ddoubleNV
ffloatNV
pconst char*String (Eingabe)
Pvoid* (veränderbarer Puffer)String (Ausgabe)

Beispiele:

  • "(d)d" — ein double-Argument, gibt double zurück (z. B. sqrt)
  • "(p)L" — ein String-Argument, gibt unsigned long zurück (z. B. strlen)
  • "(ppi)i" — zwei Strings + int, gibt int zurück
  • "()i" — keine Argumente, gibt int zurück (z. B. getpid)

Bibliothekserkennung

use Peta::FFI qw(scan);

my $libs = scan();
# Gibt Hashref zurück: { "libz.so.1" => "/usr/lib/libz.so.1", ... }

for my $soname (sort keys %$libs) {
    print "$soname => $libs->{$soname}\n";
}

scan() ruft ldconfig -p auf, um alle auf dem System verfügbaren Shared Libraries aufzulisten.

Schicht 1: Fertige Bindings

Schicht-1-Module bieten Perl-native APIs für bestimmte C-Bibliotheken mit korrekter Argumentvalidierung, Rückgabewertkonvertierung und Fehlerbehandlung. Keine Typsignaturen nötig — einfach Funktionen aufrufen.

Peta::FFI::Libc

Direkte Bindings zu libc-Funktionen, nach Kategorie gruppiert:

Prozess: getpid, getppid, getuid, getgid, geteuid, getegid

Strings: strlen, strerror

Umgebung: getenv, setenv, unsetenv

Mathematik: abs, labs

System: sleep, usleep, gethostname, uname

Dateioperationen: access, unlink, rmdir, mkdir, chmod, chown

use Peta::FFI::Libc qw(getpid gethostname uname);

print "PID: ", getpid(), "\n";
print "Host: ", gethostname(), "\n";

my @info = uname();
print "OS: $info[0] $info[2] ($info[4])\n";

Peta::FFI::UUID

Bindings zu libuuid (muss auf dem System installiert sein):

use Peta::FFI::UUID qw(uuid_generate uuid_generate_random);

my $uuid = uuid_generate();           # z. B. "550e8400-e29b-41d4-a716-446655440000"
my $rand = uuid_generate_random();    # zufallsbasierte UUID

Funktionen: uuid_generate, uuid_generate_random, uuid_generate_time, uuid_parse, uuid_is_null, uuid_unparse.

Falls libuuid nicht installiert ist, bricht use Peta::FFI::UUID mit einer Diagnosemeldung ab.

Peta::FFI::GMP (Math::GMP)

Ganzzahlarithmetik mit beliebiger Genauigkeit über libgmp. Integriert sich unter dem Klassennamen Math::GMP für Kompatibilität mit CPANs Math::GMP:

use Math::GMP;

my $big = Math::GMP->new("123456789012345678901234567890");
my $sum = $big + 42;
print "$sum\n";

GMP-Ganzzahlen sind heap-allozierte mpz_t-Werte, die als gesegnete Referenzen gespeichert werden. Operatorüberladung (+, -, *, /, %, **, <=>, "") funktioniert identisch zum XS-Modul.

Falls libgmp nicht installiert ist, bricht use Math::GMP mit einer Diagnosemeldung ab.

Wann FFI statt nativer Module verwenden

SzenarioEmpfehlung
Gängiges CPAN-Modul (List::Util usw.)Natives Modul (bereits eingebaut)
Systembibliothek noch ohne WrapperSchicht-0-Rohes-FFI
Häufige Aufrufe derselben BibliothekSchicht-1-Bindings anfordern
Einmaliges ExperimentSchicht-0-Rohes-FFI

Schicht-0-FFI hat pro Aufruf Overhead durch Argument-Marshalling und libffi-Dispatch. Schicht-1-Bindings rufen Rust/C direkt auf und sind schneller. Native Module sind am schnellsten — gleiche Geschwindigkeit wie eingebaute Operatoren.