0Pricing
Python Academy · Lezione

cffi: interfaccia per funzioni esterne C

Utilizzi cffi per un'interoperabilità con C più vicina allo stile Python, con dichiarazioni C inline.

cffi: interfaccia per funzioni esterne C è una lezione Python Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Python Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Python Academy include 4 lezioni in totale.

Che cos'è cffi?

cffi (C Foreign Function Interface) consente di chiamare codice C da Python utilizzando dichiarazioni C anziché classi ctypes. È più conforme allo stile Python e spesso più sicuro.

# pip install cffi
from cffi import FFI
ffi = FFI()

ffi.cdef("double sqrt(double x);")
libm = ffi.dlopen(None)   # current process
print(libm.sqrt(2.0))     # 1.4142...

Modalità ABI e API

ffi.dlopen() è la modalità ABI: chiama una libreria condivisa esistente in fase di esecuzione. La modalità API compila un wrapper C ed è più veloce e robusta.

from cffi import FFI
ffi = FFI()

# ABI mode (no compile step):
ffi.cdef("int abs(int x);")
libc = ffi.dlopen("libc.so.6")  # Linux
print(libc.abs(-42))   # 42

Dichiarazioni cdef

Utilizzi ffi.cdef() per dichiarare le firme delle funzioni C, le strutture e i typedef che desidera utilizzare da Python.

from cffi import FFI
ffi = FFI()

ffi.cdef("""
    typedef struct {
        double x;
        double y;
    } Point;

    double distance(Point a, Point b);
""")

# lib = ffi.dlopen("mylib.so")

Creazione di strutture C

Utilizzi ffi.new() per allocare una struttura C e impostarne i campi da Python.

from cffi import FFI
ffi = FFI()

ffi.cdef("typedef struct { int x; int y; } Vec2;")
lib = ffi.dlopen(None)

v = ffi.new("Vec2 *")
v.x = 3
v.y = 4
print(v.x, v.y)   # 3 4

Stringhe e buffer

Utilizzi ffi.new("char[]", n) per i buffer modificabili e ffi.string(ptr) per convertire un puntatore a una stringa C in bytes Python.

from cffi import FFI
ffi = FFI()

buf = ffi.new("char[]", b"hello world")
print(ffi.string(buf))   # b"hello world"

# Mutable buffer for output:
out = ffi.new("char[128]")
# c_func(out, 128)  # fill the buffer
# result = ffi.string(out).decode()

Modalità API con verify

La modalità API compila un piccolo modulo wrapper C per una maggiore sicurezza dei tipi e prestazioni migliori. Utilizzi ffi.set_source() e compili offline.

from cffi import FFI
ffi = FFI()

ffi.cdef("int add(int a, int b);")
ffi.set_source("_mylib",
    """
    int add(int a, int b) { return a + b; }
    """
)

# Build: python build_mylib.py
# from _mylib import ffi, lib
# print(lib.add(3, 4))   # 7

Callback da C a Python

Utilizzi ffi.callback() per racchiudere una funzione Python in un puntatore a funzione C che può essere passato a una libreria C.

from cffi import FFI
ffi = FFI()
ffi.cdef("typedef int (*compare_fn)(int, int);")

@ffi.callback("int(int, int)")
def compare(a, b):
    return a - b

# pass compare to a C sort function

Gestione della memoria

Gli oggetti allocati con ffi.new() appartengono a Python e vengono liberati automaticamente. Utilizzi ffi.gc(ptr, destructor) per associare un distruttore personalizzato.

from cffi import FFI
ffi = FFI()

# ptr freed when Python GC collects it:
buf = ffi.new("int[10]")
buf[0] = 42
print(buf[0])   # 42

# Custom destructor:
# ptr = ffi.gc(lib.alloc(), lib.free)

cffi e ctypes

cffi utilizza stringhe di dichiarazione C, più naturali per gli sviluppatori C, mentre ctypes utilizza classi Python. La modalità API di cffi è più veloce; ctypes non richiede compilazione.

# ctypes approach:
import ctypes
libc = ctypes.CDLL("libc.so.6")
libc.abs.restype = ctypes.c_int
libc.abs.argtypes = [ctypes.c_int]
print(libc.abs(-5))   # 5

# cffi approach:
from cffi import FFI; ffi = FFI()
ffi.cdef("int abs(int);")
lib = ffi.dlopen(None)
print(lib.abs(-5))    # 5

Utilizzo di cffi con NumPy

Passi direttamente i dati di un array NumPy a C tramite cffi usando ffi.cast() e il puntatore ctypes.data dell'array.

import numpy as np
from cffi import FFI
ffi = FFI()

arr = np.array([1.0, 2.0, 3.0])
ptr = ffi.cast("double *", arr.ctypes.data)
# Now ptr can be passed to a C function expecting double*

Gestione degli errori con cffi

Le funzioni C in genere segnalano gli errori tramite valori restituiti. Controlli i valori restituiti e utilizzi ffi.errno per i codici di errore POSIX.

import errno as errno_mod
from cffi import FFI
ffi = FFI()
ffi.cdef("int open(const char *path, int flags);")
lib = ffi.dlopen(None)

fd = lib.open(b"/nonexistent", 0)
if fd == -1:
    err = ffi.errno
    raise OSError(err, "open failed")

Verifica rapida

Quale metodo utilizza cffi per dichiarare le firme delle funzioni C che desidera chiamare?

Riepilogo

cffi utilizza ffi.cdef() per dichiarare le firme C e ffi.dlopen() per chiamare librerie in modalità ABI. La modalità API compila un wrapper per ottenere prestazioni migliori. Utilizzi ffi.new() per la memoria C e ffi.callback() per i callback da Python a C.

Domande Frequenti

La lezione «cffi: interfaccia per funzioni esterne C» è gratuita?

Sì — il testo completo di «cffi: interfaccia per funzioni esterne C» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Python Academy, passa a CoddyKit PRO. Il corso Python Academy include 4 lezioni in totale.

Cosa imparerò in «cffi: interfaccia per funzioni esterne C»?

Utilizzi cffi per un'interoperabilità con C più vicina allo stile Python, con dichiarazioni C inline. Eserciti Python Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.

Ho bisogno di esperienza per iniziare Python Academy?

Non è richiesta alcuna esperienza precedente. Python Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.

Quanto tempo richiede la lezione «cffi: interfaccia per funzioni esterne C»?

La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.

Posso scrivere ed eseguire codice in questa lezione Python Academy?

Sì. Ogni lezione Python Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.

Tutte le lezioni di questo corso

  1. Perché le estensioni C? Casi d'uso e compromessi
  2. ctypes: chiamare librerie C da Python
  3. cffi: interfaccia per funzioni esterne C
  4. Scrittura di un modulo di estensione C per Python
← Torna a Python Academy