Python Academy · Lektion

cffi: C Foreign Function Interface

Brug cffi til mere Pythonisk C-interoperabilitet med indlejrede C-deklarationer.

Lektion 3 af 413 trin

cffi: C Foreign Function Interface er en gratis Python Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i Python Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Python Academy-kurset indeholder 4 lektioner i alt.

Hvad er cffi?

cffi (C-grænseflade til eksterne funktioner) lader dig kalde C-kode fra Python ved hjælp af C-deklarationer i stedet for ctypes-klasser. Det er mere Python-agtigt og ofte sikrere.

# 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...

ABI-tilstand kontra API-tilstand

ffi.dlopen() er ABI-tilstand — den kalder et eksisterende delt bibliotek under kørsel. API-tilstand kompilerer en C-indpakning og er hurtigere og mere robust.

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

cdef-deklarationer

Brug ffi.cdef() til at deklarere C-funktionssignaturer, strukturer og typedefs, som du vil bruge fra 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")

Oprettelse af C-strukturer

Brug ffi.new() til at allokere en C-struktur og angive dens felter fra 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

Strenge og buffere

Brug ffi.new("char[]", n) til ændringsbare buffere og ffi.string(ptr) til at konvertere en C-strengpointer til Python-bytes.

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()

API-tilstand med verify

API-tilstand kompilerer et lille C-indpakningsmodul for bedre typesikkerhed og ydeevne. Brug ffi.set_source(), og byg 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

Tilbagekald fra C til Python

Brug ffi.callback() til at pakke en Python-funktion ind som en C-funktionspointer, der kan videregives til et C-bibliotek.

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

Hukommelseshåndtering

Objekter, der er allokeret med ffi.new(), ejes af Python og frigives automatisk. Brug ffi.gc(ptr, destructor) til at tilknytte en brugerdefineret destruktør.

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 kontra ctypes

cffi bruger C-deklarationsstrenge, som er mere naturlige for C-udviklere, mens ctypes bruger Python-klasser. cffi's API-tilstand er hurtigere, mens ctypes ikke kræver kompilering.

# 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

Brug af cffi med NumPy

Videregiv data fra et NumPy-array direkte til C via cffi ved hjælp af ffi.cast() og arrayets ctypes.data-pointer.

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*

Fejlhåndtering med cffi

C-funktioner signalerer typisk fejl via returværdier. Kontrollér returværdierne, og brug ffi.errno til POSIX-fejlkoder.

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")

Hurtigt tjek

Hvilken metode bruger cffi til at deklarere de C-funktionssignaturer, du vil kalde?

Opsummering

cffi bruger ffi.cdef() til at deklarere C-signaturer og ffi.dlopen() til biblioteksopkald i ABI-tilstand. API-tilstand kompilerer en indpakning for bedre ydeevne. Brug ffi.new() til C-hukommelse og ffi.callback() til tilbagekald fra Python til C.

Gratis at komme i gang

Lær Python med en AI-underviser — gratis

Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.

Kurser
76
Lektioner
320

Ofte stillede spørgsmål

Er lektionen “cffi: C Foreign Function Interface” gratis?

Ja — hele teksten til “cffi: C Foreign Function Interface” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af Python Academy-kurset, skal du opgradere til CoddyKit PRO. Python Academy-kurset indeholder 4 lektioner i alt.

Hvad lærer jeg i “cffi: C Foreign Function Interface”?

Brug cffi til mere Pythonisk C-interoperabilitet med indlejrede C-deklarationer. Du øver dig i Python Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.

Skal jeg have erfaring for at begynde på Python Academy?

Der kræves ingen tidligere erfaring. Python Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.

Hvor lang tid tager lektionen “cffi: C Foreign Function Interface”?

De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.

Kan jeg skrive og køre kode i denne Python Academy-lektion?

Ja. Alle Python Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.

Alle lektioner i dette kursus

  1. Hvorfor C-udvidelser? Anvendelser og afvejninger
  2. ctypes: Kald af C-biblioteker fra Python
  3. cffi: C Foreign Function Interface
  4. Skrivning af et Python-C-udvidelsesmodul
← Tilbage til Python Academy