Python Academy · Lektion

Skriva en Python C Extension-modul

Bygg ett enkelt .so-tillägg med Python/C API.

Lektion 4 av 413 steg

Skriva en Python C Extension-modul är en gratis lektion i Python Academy på CoddyKit. Detta är lektion 4 av 4. Ni kan läsa hela lektionen gratis nedan och sedan öva praktiskt i webbläsaren med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt. Den ingår i lärvägen för Python Academy, och Era framsteg synkroniseras mellan webben och CoddyKit-appen. Kursen i Python Academy innehåller totalt 4 lektioner.

C-tilläggets uppbyggnad

Ett minimalt C-tillägg består av: metodfunktioner, en metodtabell, en struct för moduldefinitionen och en PyInit_-ingångspunkt.

// myext.c skeleton
#include <Python.h>

static PyObject* say_hello(PyObject* self, PyObject* args) {
    Py_RETURN_NONE;
}

static PyMethodDef methods[] = {
    {"say_hello", say_hello, METH_NOARGS, "Print hello"},
    {NULL, NULL, 0, NULL}
};

static struct PyModuleDef module = {
    PyModuleDef_HEAD_INIT, "myext", NULL, -1, methods
};

PyMODINIT_FUNC PyInit_myext(void) {
    return PyModule_Create(&module);
}

Parsa argument

PyArg_ParseTuple(args, "ii", &a, &b) parsar Python-argument till C-variabler. Formatkoder: i=int, d=double, s=char*, O=PyObject*.

static PyObject* add(PyObject* self, PyObject* args) {
    int a, b;
    if (!PyArg_ParseTuple(args, "ii", &a, &b))
        return NULL;
    return PyLong_FromLong(a + b);
}

Returnera värden

Skapa Python-returvärden med: PyLong_FromLong, PyFloat_FromDouble, PyUnicode_FromString, Py_BuildValue.

// Return a Python tuple (int, float)
static PyObject* stats(PyObject* self, PyObject* args) {
    int n = 10;
    double avg = 5.0;
    return Py_BuildValue("(id)", n, avg);
    // Py_BuildValue format: i=int d=double s=str
}

Referensräkning

Varje PyObject* har ett referensantal. Använd Py_INCREF/Py_DECREF försiktigt. Returvärden från C-funktioner överlåter ägarskapet till anroparen (stulna referenser).

static PyObject* make_list(PyObject* self, PyObject* args) {
    PyObject* lst = PyList_New(3);
    for (int i = 0; i < 3; i++) {
        // PyList_SET_ITEM steals the reference:
        PyList_SET_ITEM(lst, i, PyLong_FromLong(i));
    }
    return lst;   // caller owns the list
}

Utlösa undantag

Använd PyErr_SetString(PyExc_ValueError, "msg") för att utlösa ett Python-undantag från C och returnera sedan NULL.

static PyObject* safe_div(PyObject* self, PyObject* args) {
    int a, b;
    if (!PyArg_ParseTuple(args, "ii", &a, &b)) return NULL;
    if (b == 0) {
        PyErr_SetString(PyExc_ZeroDivisionError, "division by zero");
        return NULL;
    }
    return PyLong_FromLong(a / b);
}

setup.py för C-tillägg

Använd setuptools.Extension för att deklarera C-källfilerna. Bygg med python setup.py build_ext --inplace.

# setup.py
from setuptools import setup, Extension

setup(
    name="myext",
    ext_modules=[
        Extension(
            "myext",
            sources=["myext.c"],
            extra_compile_args=["-O2"],
        )
    ]
)
# python setup.py build_ext --inplace
# import myext; myext.add(3, 4)

Använda det byggda tillägget

När tillägget har byggts importerar ni det som vilken Python-modul som helst. Python hittar det genom att leta efter myext.so (eller .pyd i Windows).

# After: python setup.py build_ext --inplace
import myext
print(myext.add(3, 4))        # 7
print(myext.safe_div(10, 2))  # 5
# myext.safe_div(1, 0)         # ZeroDivisionError

Nyckelordsargument

Använd PyArg_ParseTupleAndKeywords med en lista över nyckelord för att stödja nyckelordsargument i C-funktioner.

static char* kwargs[] = {"x", "y", NULL};

static PyObject* hypot_c(PyObject* self,
                          PyObject* args,
                          PyObject* kw) {
    double x, y;
    if (!PyArg_ParseTupleAndKeywords(args, kw, "dd",
                                     kwargs, &x, &y))
        return NULL;
    return PyFloat_FromDouble(sqrt(x*x + y*y));
}

Konstanter på modulnivå

Lägg till heltals- eller strängkonstanter i modulen i PyInit_ med hjälp av PyModule_AddIntConstant.

PyMODINIT_FUNC PyInit_myext(void) {
    PyObject* m = PyModule_Create(&module);
    if (!m) return NULL;
    PyModule_AddIntConstant(m, "VERSION", 1);
    PyModule_AddStringConstant(m, "AUTHOR", "Alice");
    return m;
}

Frigöra GIL

Omslut rent C-arbete med Py_BEGIN_ALLOW_THREADS / Py_END_ALLOW_THREADS så att andra Python-trådar kan köras medan C-koden körs.

static PyObject* heavy(PyObject* self, PyObject* args) {
    long n;
    if (!PyArg_ParseTuple(args, "l", &n)) return NULL;
    long result;
    Py_BEGIN_ALLOW_THREADS
        result = slow_c_computation(n);  // GIL released
    Py_END_ALLOW_THREADS
    return PyLong_FromLong(result);
}

Testa tillägget

Testa C-tillägg via deras Python-gränssnitt med pytest. Inga särskilda C-testverktyg krävs.

# test_myext.py
import pytest
import myext

def test_add(): assert myext.add(3, 4) == 7
def test_zero_div():
    with pytest.raises(ZeroDivisionError):
        myext.safe_div(1, 0)

Snabbkontroll

Vad måste en C-tilläggsfunktion returnera för att signalera att ett Python-undantag har satts?

Sammanfattning

Ett C-tillägg behöver: metodfunktioner (parsa argument och returnera PyObject*), en metodtabell, en struct för moduldefinitionen och PyInit_name(). Utlös undantag genom att sätta dem med PyErr_SetString och returnera NULL. Frigör GIL vid rent C-arbete.

Gratis att börja

Lär dig Python med en AI-lärare – gratis

Skriv och kör riktig kod i webbläsaren, få omedelbar hjälp av en AI-lärare dygnet runt och fortsätt där du slutade – på webben eller i appen.

Kurser
76
Lektioner
320

Vanliga frågor

Är lektionen ”Skriva en Python C Extension-modul” gratis?

Ja – hela texten till ”Skriva en Python C Extension-modul” kan läsas gratis här på webben. Om Ni vill öva interaktivt med en inbyggd kodredigerare och en AI-handledare som är tillgänglig dygnet runt och låsa upp resten av kursen i Python Academy, kan Ni uppgradera till CoddyKit PRO. Kursen i Python Academy innehåller totalt 4 lektioner.

Vad lär jag mig i ”Skriva en Python C Extension-modul”?

Bygg ett enkelt .so-tillägg med Python/C API. Ni övar på Python Academy med praktisk kod som körs direkt i webbläsaren, medan en AI-handledare som är tillgänglig dygnet runt svarar på Era frågor under lektionen.

Behöver jag någon erfarenhet för att börja lära mig Python Academy?

Du behöver inga förkunskaper. Utbildningen i Python Academy på CoddyKit är upplagd för allt från nybörjare till avancerade elever, så att du kan börja här eller från början och gå fram i din egen takt. Detta är lektion 4 av 4.

Hur lång tid tar lektionen ”Skriva en Python C Extension-modul”?

De flesta CoddyKit-lektioner tar cirka 5–10 minuter. Varje lektion är kort och interaktiv, så att du gör stadiga framsteg och kan fortsätta precis där du slutade – på webben eller i appen.

Kan jag skriva och köra kod i den här Python Academy-lektionen?

Ja. Varje Python Academy-lektion innehåller en inbyggd kodredigerare, så att du kan skriva och köra riktig kod direkt i webbläsaren och få omedelbar AI-feedback – utan lokal installation.

Alla lektioner i den här kursen

  1. Varför C-tillägg? Användningsområden och avvägningar
  2. ctypes: anropa C-bibliotek från Python
  3. cffi: C Foreign Function Interface
  4. Skriva en Python C Extension-modul
← Tillbaka till Python Academy