Python Academy · Oppitunti

cffi: C:n vierasfunktiorajapinta

Käyttäkää cffiä Python-tyylisempään C-yhteentoimivuuteen ja upotettuihin C-määrityksiin.

Oppitunti 3/413 vaihetta

cffi: C:n vierasfunktiorajapinta on ilmainen Python Academy-oppitunti CoddyKitissä. Tämä on oppitunti 3/4. Voit lukea koko oppitunnin alta ilmaiseksi ja harjoitella sen jälkeen käytännössä selaimessa sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla. Oppitunti kuuluu Python Academy-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. Python Academy-kurssilla on yhteensä 4 oppituntia.

Mikä on cffi?

cffi (C Foreign Function Interface) mahdollistaa C-koodin kutsumisen Pythonista C-määrittelyjen avulla ctypes-luokkien sijaan. Se on Python-tyylisempi ja usein turvallisempi.

# 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- ja API-tila

ffi.dlopen() käyttää ABI-tilaa — se kutsuu olemassa olevaa jaettua kirjastoa ajon aikana. API-tila kääntää C-kääreen, joten se on nopeampi ja vankempi.

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-määrittelyt

Käyttäkää ffi.cdef()-kutsua niiden C-funktioiden allekirjoitusten, rakenteiden ja typedef-määritteiden ilmoittamiseen, joita haluatte käyttää Pythonista.

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

C-rakenteiden luominen

Käyttäkää ffi.new()-kutsua C-rakenteen varaamiseen ja sen kenttien määrittämiseen Pythonista.

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

Merkkijonot ja puskurit

Käyttäkää ffi.new("char[]", n)-kutsua muokattaviin puskurivarauksiin ja ffi.string(ptr)-kutsua C-merkkijono-osoittimen muuntamiseen Pythonin tavuiksi.

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-tila ja verify

API-tila kääntää pienen C-kääremoduulin, joka parantaa tyyppiturvallisuutta ja suorituskykyä. Käyttäkää ffi.set_source()-kutsua ja kääntäkää offline-tilassa.

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

Takaisinkutsut C:stä Pythoniin

Käyttäkää ffi.callback()-kutsua käärimään Python-funktio C-funktio-osoittimeksi, jonka voitte välittää C-kirjastolle.

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

Muistinhallinta

ffi.new()-kutsulla varatut oliot ovat Pythonin omistuksessa, ja ne vapautetaan automaattisesti. Käyttäkää ffi.gc(ptr, destructor)-kutsua liittääksenne olioon oman vapautusfunktion.

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

cffi käyttää C-määrittelymerkkijonoja, jotka ovat C-kehittäjille luontevampia, kun taas ctypes käyttää Python-luokkia. cffin API-tila on nopeampi, mutta ctypes ei vaadi kääntämistä.

# 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

cffin käyttäminen NumPyn kanssa

Välittäkää NumPy-taulukon tiedot suoraan C-koodille cffin avulla käyttämällä ffi.cast()-kutsua ja taulukon ctypes.data-osoitinta.

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*

cffin virheenkäsittely

C-funktiot ilmoittavat virheistä yleensä paluuarvojen avulla. Tarkistakaa paluuarvot ja käyttäkää ffi.errno-muuttujaa POSIX-virhekoodeille.

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

Pikatarkistus

Mitä menetelmää cffi käyttää kutsuttavien C-funktioiden allekirjoitusten ilmoittamiseen?

Kertaus

cffi käyttää ffi.cdef()-kutsua C-funktioiden allekirjoitusten ilmoittamiseen ja ffi.dlopen()-kutsua ABI-tilan kirjastokutsuihin. API-tila kääntää kääreen paremman suorituskyvyn saavuttamiseksi. Käyttäkää ffi.new()-kutsua C-muistin varaamiseen ja ffi.callback()-kutsua Pythonista C:hen suuntautuviin takaisinkutsuihin.

Aloita maksutta

Opi Python tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
76
Oppitunnit
320

Usein kysytyt kysymykset

Onko oppitunti ”cffi: C:n vierasfunktiorajapinta” ilmainen?

Kyllä – oppitunnin ”cffi: C:n vierasfunktiorajapinta” koko tekstin voi lukea täällä verkossa ilmaiseksi. Jos haluat harjoitella interaktiivisesti sisäänrakennetulla koodieditorilla ja ympäri vuorokauden käytettävissä olevan tekoälytuutorin avulla sekä avata koko Python Academy-kurssin, päivitä CoddyKit PROhon. Python Academy-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”cffi: C:n vierasfunktiorajapinta”?

Käyttäkää cffiä Python-tyylisempään C-yhteentoimivuuteen ja upotettuihin C-määrityksiin. Harjoittelet Python Academy-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni Python Academy-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin Python Academy-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 3/4.

Kuinka kauan ”cffi: C:n vierasfunktiorajapinta”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä Python Academy-oppitunnilla?

Kyllä. Jokainen Python Academy-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Miksi C-laajennuksia käytetään? Käyttötapaukset ja kompromissit
  2. ctypes: C-kirjastojen kutsuminen Pythonista
  3. cffi: C:n vierasfunktiorajapinta
  4. Pythonin C-laajennusmoduulin kirjoittaminen
← Takaisin: Python Academy