Skrivning af et Python-C-udvidelsesmodul
Opret en enkel .so-udvidelse med Python/C-API'et.
Skrivning af et Python-C-udvidelsesmodul er en gratis Python Academy-lektion på CoddyKit. Dette er lektion 4 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.
Opbygningen af en C-udvidelse
En minimal C-udvidelse har: metodefunktioner, en metodetabel, en moduldefinitionsstruktur og et PyInit_-indgangspunkt.
// 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);
}Fortolkning af argumenter
PyArg_ParseTuple(args, "ii", &a, &b) fortolker Python-argumenter til 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);
}Returnering af værdier
Opret Python-returværdier 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
}Referencetælling
Hvert PyObject* har en referencetæller. Brug Py_INCREF/Py_DECREF med omtanke. Returværdier fra C-funktioner giver den kaldende part ejerskab (stjålne referencer).
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
}Udløsning af undtagelser
Brug PyErr_SetString(PyExc_ValueError, "msg") til at udløse en Python-undtagelse fra C, og returnér derefter 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 til C-udvidelser
Brug setuptools.Extension til at deklarere C-kildefilerne. Byg 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)Brug af den byggede udvidelse
Når udvidelsen er bygget, skal du importere den som ethvert andet Python-modul. Python finder den ved at lede efter myext.so (eller .pyd på 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) # ZeroDivisionErrorNavngivne argumenter
Brug PyArg_ParseTupleAndKeywords sammen med en liste over nøgleord for at understøtte navngivne argumenter 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å modulniveau
Tilføj heltals- eller strengkonstanter til modulet i PyInit_ ved hjælp af 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;
}Frigivelse af GIL
Pak rent C-arbejde ind i Py_BEGIN_ALLOW_THREADS / Py_END_ALLOW_THREADS for at lade andre Python-tråde køre, mens C-koden udføres.
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);
}Test af udvidelsen
Test C-udvidelser gennem deres Python-grænseflade med pytest. Der kræves ingen særlige C-testværktøjer.
# 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)Hurtigt tjek
Hvad skal en funktion i en C-udvidelse returnere for at angive, at der er blevet sat en Python-undtagelse?
Opsummering
En C-udvidelse kræver: metodefunktioner (fortolkning af argumenter, returnering af PyObject*), en metodetabel, en moduldefinitionsstruktur og PyInit_name(). Udløs undtagelser ved at angive dem med PyErr_SetString og returnere NULL. Frigiv GIL ved rent C-arbejde.
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 “Skrivning af et Python-C-udvidelsesmodul” gratis?
Ja — hele teksten til “Skrivning af et Python-C-udvidelsesmodul” 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 “Skrivning af et Python-C-udvidelsesmodul”?
Opret en enkel .so-udvidelse med Python/C-API'et. 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 4 af 4.
Hvor lang tid tager lektionen “Skrivning af et Python-C-udvidelsesmodul”?
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
- Hvorfor C-udvidelser? Anvendelser og afvejninger
- ctypes: Kald af C-biblioteker fra Python
- cffi: C Foreign Function Interface
- Skrivning af et Python-C-udvidelsesmodul