Pythonin C-laajennusmoduulin kirjoittaminen
Rakentakaa yksinkertainen .so-laajennus Python/C API:n avulla.
Pythonin C-laajennusmoduulin kirjoittaminen on ilmainen Python Academy-oppitunti CoddyKitissä. Tämä on oppitunti 4/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.
C-laajennuksen rakenne
Minimaalisessa C-laajennuksessa on metodifunktioita, metoditaulukko, moduulin määrittelyrakenne ja PyInit_-aloituspiste.
// 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);
}Argumenttien jäsentäminen
PyArg_ParseTuple(args, "ii", &a, &b) jäsentää Python-argumentit C-muuttujiksi. Muotoilukoodit ovat: i=int, d=double, s=char* ja 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);
}Paluuarvojen muodostaminen
Muodostakaa Pythonin paluuarvot seuraavilla funktioilla: PyLong_FromLong, PyFloat_FromDouble, PyUnicode_FromString ja 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
}Viitelaskenta
Jokaisella PyObject*-oliolla on viitemäärä. Käyttäkää Py_INCREF- ja Py_DECREF-makroja huolellisesti. C-funktioiden palauttamat paluuarvot antavat omistajuuden kutsujalle (varastetut viitteet).
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
}Poikkeusten nostaminen
Käyttäkää PyErr_SetString(PyExc_ValueError, "msg")-kutsua Python-poikkeuksen nostamiseen C:stä ja palauttakaa sen jälkeen 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);
}C-laajennusten setup.py
Käyttäkää setuptools.Extension-luokkaa C-lähdetiedostojen ilmoittamiseen. Kääntäkää komennolla 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)Käännetyn laajennuksen käyttäminen
Kun laajennus on käännetty, tuokaa se käyttöön kuten mikä tahansa Python-moduuli. Python löytää sen etsimällä tiedostoa myext.so (tai Windowsissa tiedostoa .pyd).
# 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) # ZeroDivisionErrorAvainsana-argumentit
Käyttäkää PyArg_ParseTupleAndKeywords-funktiota yhdessä avainsanaluettelon kanssa, jotta C-funktiot tukevat avainsana-argumentteja.
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));
}Moduulitason vakiot
Lisätkää kokonaisluku- tai merkkijonovakioita moduuliin PyInit_-funktion avulla käyttämällä PyModule_AddIntConstant-funktiota.
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;
}GIL:n vapauttaminen
Ympäröikää puhdas C-työ komennoilla Py_BEGIN_ALLOW_THREADS ja Py_END_ALLOW_THREADS, jotta muut Python-säikeet voivat suorittaa koodia C-koodin aikana.
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);
}Laajennuksen testaaminen
Testatkaa C-laajennuksia niiden Python-rajapinnan kautta pytestillä. Erillisiä C-testityökaluja ei tarvita.
# 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)Pikatarkistus
Mitä C-laajennuksen funktion on palautettava osoittaakseen, että Python-poikkeus on asetettu?
Kertaus
C-laajennus tarvitsee metodifunktiot (argumenttien jäsentäminen ja PyObject*-arvon palauttaminen), metoditaulukon, moduulin määrittelyrakenteen ja PyInit_name()-funktion. Nostakaa poikkeuksia asettamalla ne PyErr_SetString-funktiolla ja palauttamalla NULL. Vapauttakaa GIL puhtaan C-työn ajaksi.
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 ”Pythonin C-laajennusmoduulin kirjoittaminen” ilmainen?
Kyllä – oppitunnin ”Pythonin C-laajennusmoduulin kirjoittaminen” 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 ”Pythonin C-laajennusmoduulin kirjoittaminen”?
Rakentakaa yksinkertainen .so-laajennus Python/C API:n avulla. 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 4/4.
Kuinka kauan ”Pythonin C-laajennusmoduulin kirjoittaminen”-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
- Miksi C-laajennuksia käytetään? Käyttötapaukset ja kompromissit
- ctypes: C-kirjastojen kutsuminen Pythonista
- cffi: C:n vierasfunktiorajapinta
- Pythonin C-laajennusmoduulin kirjoittaminen