0Pricing
Python Academy · Lekcja

cffi: interfejs funkcji zewnętrznych C

Proszę używać cffi do bardziej pythonicznej integracji z C, z wbudowanymi deklaracjami C.

cffi: interfejs funkcji zewnętrznych C to bezpłatna lekcja Python Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej Python Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs Python Academy zawiera 4 lekcji w sumie.

Czym jest cffi?

cffi (C Foreign Function Interface) umożliwia wywoływanie kodu C z poziomu Pythona za pomocą deklaracji C zamiast klas ctypes. Jest bardziej zgodne z idiomami Pythona i często bezpieczniejsze.

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

Tryb ABI a tryb API

ffi.dlopen() to tryb ABI — wywołuje istniejącą bibliotekę współdzieloną w czasie działania. Tryb API kompiluje wrapper C, dzięki czemu jest szybszy i bardziej niezawodny.

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

Deklaracje cdef

Proszę użyć ffi.cdef() do zadeklarowania sygnatur funkcji C, struktur i typedefów, które mają być używane z poziomu Pythona.

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

Tworzenie struktur C

Proszę użyć ffi.new(), aby zaalokować strukturę C i ustawić jej pola z poziomu Pythona.

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

Ciągi znaków i bufory

Proszę użyć ffi.new("char[]", n) dla modyfikowalnych buforów oraz ffi.string(ptr), aby przekonwertować wskaźnik do ciągu znaków C na bajty Pythona.

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

Tryb API z verify

Tryb API kompiluje niewielki moduł wrappera C, zapewniając lepsze bezpieczeństwo typów i wydajność. Proszę użyć ffi.set_source() i przeprowadzić kompilację 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

Callbacki z C do Pythona

Proszę użyć ffi.callback(), aby opakować funkcję Pythona jako wskaźnik do funkcji C, który można przekazać do biblioteki 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

Zarządzanie pamięcią

Obiekty zaalokowane za pomocą ffi.new() należą do Pythona i są automatycznie zwalniane. Proszę użyć ffi.gc(ptr, destructor), aby dołączyć własny destruktor.

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

cffi używa ciągów deklaracji C, które są bardziej naturalne dla programistów C, natomiast ctypes korzysta z klas Pythona. Tryb API cffi jest szybszy, a ctypes nie wymaga kompilacji.

# 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

Używanie cffi z NumPy

Dane tablicy NumPy można przekazywać bezpośrednio do C za pośrednictwem cffi, używając ffi.cast() i wskaźnika ctypes.data tablicy.

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*

Obsługa błędów w cffi

Funkcje C zazwyczaj sygnalizują błędy za pomocą wartości zwracanych. Należy sprawdzać wartości zwracane i używać ffi.errno dla kodów błędów 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")

Szybkie sprawdzenie

Jakiej metody używa cffi do deklarowania sygnatur funkcji C, które mają być wywoływane?

Podsumowanie

cffi używa ffi.cdef() do deklarowania sygnatur C oraz ffi.dlopen() do wywoływania bibliotek w trybie ABI. Tryb API kompiluje wrapper, zapewniając lepszą wydajność. Proszę używać ffi.new() do zarządzania pamięcią C oraz ffi.callback() do callbacków z Pythona do C.

Często zadawane pytania

Czy lekcja „cffi: interfejs funkcji zewnętrznych C” jest bezpłatna?

Tak — pełny tekst „cffi: interfejs funkcji zewnętrznych C” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu Python Academy, przejdź na CoddyKit PRO. Kurs Python Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „cffi: interfejs funkcji zewnętrznych C”?

Proszę używać cffi do bardziej pythonicznej integracji z C, z wbudowanymi deklaracjami C. Ćwiczysz Python Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć Python Academy?

Nie wymagamy żadnego doświadczenia. Python Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „cffi: interfejs funkcji zewnętrznych C”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji Python Academy?

Tak. Każda lekcja Python Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Po co rozszerzenia C? Zastosowania i kompromisy
  2. ctypes: wywoływanie bibliotek C z Pythona
  3. cffi: interfejs funkcji zewnętrznych C
  4. Pisanie modułu rozszerzeń C dla Pythona
← Powrót do Python Academy