Manufaktur industri
Industri Internet of Things | bahan industri | Pemeliharaan dan Perbaikan Peralatan | Pemrograman industri |
home  MfgRobots >> Manufaktur industri >  >> Industrial programming >> Python

Python - Pemrograman Ekstensi dengan C

Halaman SebelumnyaHalaman Berikutnya

Kode apa pun yang Anda tulis menggunakan bahasa yang dikompilasi seperti C, C++, atau Java dapat diintegrasikan atau diimpor ke skrip Python lain. Kode ini dianggap sebagai "ekstensi".

Modul ekstensi Python tidak lebih dari pustaka C normal. Pada mesin Unix, library ini biasanya diakhiri dengan .so (untuk objek bersama). Pada mesin Windows, Anda biasanya melihat .dll (untuk perpustakaan yang terhubung secara dinamis).

Persyaratan untuk Menulis Ekstensi

Untuk mulai menulis ekstensi, Anda memerlukan file header Python.

Selain itu, diasumsikan bahwa Anda memiliki pengetahuan yang baik tentang C atau C++ untuk menulis Ekstensi Python apa pun menggunakan pemrograman C.

Pertama-tama lihat Ekstensi Python

Untuk tampilan pertama Anda pada modul ekstensi Python, Anda perlu mengelompokkan kode Anda menjadi empat bagian

File Header Python.h

Anda perlu menyertakan Python.h file header di file sumber C Anda, yang memberi Anda akses ke API Python internal yang digunakan untuk menghubungkan modul Anda ke penerjemah.

Pastikan untuk menyertakan Python.h sebelum header lain yang mungkin Anda perlukan. Anda harus mengikuti penyertaan dengan fungsi yang ingin Anda panggil dari Python.

Fungsi C

Tanda tangan implementasi C dari fungsi Anda selalu mengambil salah satu dari tiga bentuk berikut −

static PyObject *MyFunction( PyObject *self, PyObject *args );

static PyObject *MyFunctionWithKeywords(PyObject *self,
                                 PyObject *args,
                                 PyObject *kw);

static PyObject *MyFunctionWithNoArgs( PyObject *self );

Masing-masing dari deklarasi sebelumnya mengembalikan objek Python. Tidak ada yang namanya kekosongan function di Python seperti yang ada di C. Jika Anda tidak ingin fungsi Anda mengembalikan nilai, kembalikan C setara dengan None Python nilai. Header Python mendefinisikan makro, Py_RETURN_NONE, yang melakukan ini untuk kita.

Nama fungsi C Anda bisa apa saja yang Anda suka karena tidak pernah terlihat di luar modul ekstensi. Mereka didefinisikan sebagai statis fungsi.

Fungsi C Anda biasanya diberi nama dengan menggabungkan modul Python dan nama fungsi bersama-sama, seperti yang ditunjukkan di sini −

static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Do your stuff here. */
   Py_RETURN_NONE;
}

Ini adalah fungsi Python yang disebut fungsi di dalam modul modul . Anda akan meletakkan pointer ke fungsi C Anda ke dalam tabel metode untuk modul yang biasanya muncul berikutnya dalam kode sumber Anda.

Tabel Pemetaan Metode

Tabel metode ini adalah array sederhana dari struktur PyMethodDef. Struktur itu terlihat seperti ini

struct PyMethodDef {
   char *ml_name;
   PyCFunction ml_meth;
   int ml_flags;
   char *ml_doc;
};

Berikut adalah deskripsi anggota struktur ini −

Tabel ini perlu diakhiri dengan sentinel yang terdiri dari nilai NULL dan 0 untuk anggota yang sesuai.

Contoh

Untuk fungsi yang didefinisikan di atas, kami memiliki tabel pemetaan metode berikut −

static PyMethodDef module_methods[] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { NULL, NULL, 0, NULL }
};

Fungsi Inisialisasi

Bagian terakhir dari modul ekstensi Anda adalah fungsi inisialisasi. Fungsi ini dipanggil oleh interpreter Python ketika modul dimuat. Fungsi tersebut harus diberi nama initModul , di mana Modul adalah nama modul.

Fungsi inisialisasi perlu diekspor dari perpustakaan yang akan Anda bangun. Header Python mendefinisikan PyMODINIT_FUNC untuk menyertakan mantra yang sesuai agar hal itu terjadi untuk lingkungan tertentu tempat kami mengompilasi. Yang harus Anda lakukan adalah menggunakannya saat mendefinisikan fungsi.

Fungsi inisialisasi C Anda umumnya memiliki struktur keseluruhan berikut

PyMODINIT_FUNC initModule() {
   Py_InitModule3(func, module_methods, "docstring...");
}

Berikut adalah deskripsi Py_InitModule3 fungsi

Menyatukan ini semua terlihat seperti berikut −

#include <Python.h>

static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Do your stuff here. */
   Py_RETURN_NONE;
}

static PyMethodDef module_methods[] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { NULL, NULL, 0, NULL }
};

PyMODINIT_FUNC initModule() {
   Py_InitModule3(func, module_methods, "docstring...");
}

Contoh

Contoh sederhana yang menggunakan semua konsep di atas

#include <Python.h>

static PyObject* helloworld(PyObject* self) {
   return Py_BuildValue("s", "Hello, Python extensions!!");
}

static char helloworld_docs[] =
   "helloworld( ): Any message you want to put here!!\n";

static PyMethodDef helloworld_funcs[] = {
   {"helloworld", (PyCFunction)helloworld, 
      METH_NOARGS, helloworld_docs},
      {NULL}
};

void inithelloworld(void) {
   Py_InitModule3("helloworld", helloworld_funcs,
                  "Extension module example!");
}

Ini Py_BuildValue fungsi digunakan untuk membangun nilai Python. Simpan kode di atas dalam file hello.c. Kita akan melihat bagaimana mengkompilasi dan menginstal modul ini untuk dipanggil dari skrip Python.

Membuat dan Memasang Ekstensi

Distutil package membuatnya sangat mudah untuk mendistribusikan modul Python, baik Python murni maupun modul ekstensi, dengan cara standar. Modul didistribusikan dalam bentuk sumber dan dibuat serta diinstal melalui skrip pengaturan yang biasanya disebut setup.py sebagai berikut.

Untuk modul di atas, Anda perlu menyiapkan skrip setup.py berikut

from distutils.core import setup, Extension
setup(name='helloworld', version='1.0',  \
      ext_modules=[Extension('helloworld', ['hello.c'])])

Sekarang, gunakan perintah berikut, yang akan melakukan semua langkah kompilasi dan penautan yang diperlukan, dengan perintah dan flag compiler dan linker yang tepat, dan menyalin pustaka dinamis yang dihasilkan ke direktori yang sesuai −

$ python setup.py install

Pada sistem berbasis Unix, kemungkinan besar Anda harus menjalankan perintah ini sebagai root agar memiliki izin untuk menulis ke direktori paket situs. Ini biasanya bukan masalah di Windows.

Mengimpor Ekstensi

Setelah Anda menginstal ekstensi Anda, Anda akan dapat mengimpor dan memanggil ekstensi itu dalam skrip Python Anda sebagai berikut −

#!/usr/bin/python
import helloworld

print helloworld.helloworld()

Ini akan menghasilkan hasil berikut

Hello, Python extensions!!

Meneruskan Parameter Fungsi

Karena kemungkinan besar Anda ingin mendefinisikan fungsi yang menerima argumen, Anda dapat menggunakan salah satu tanda tangan lain untuk fungsi C Anda. Misalnya, fungsi berikut, yang menerima sejumlah parameter, akan didefinisikan seperti ini −

static PyObject *module_func(PyObject *self, PyObject *args) {
   /* Parse args and do something interesting here. */
   Py_RETURN_NONE;
}

Tabel metode yang berisi entri untuk fungsi baru akan terlihat seperti ini

static PyMethodDef module_methods[] = {
   { "func", (PyCFunction)module_func, METH_NOARGS, NULL },
   { "func", module_func, METH_VARARGS, NULL },
   { NULL, NULL, 0, NULL }
};

Anda dapat menggunakan API PyArg_ParseTuple fungsi untuk mengekstrak argumen dari satu pointer PyObject yang diteruskan ke fungsi C Anda.

Argumen pertama untuk PyArg_ParseTuple adalah argumen args. Ini adalah objek yang akan Anda parsing . Argumen kedua adalah string format yang menjelaskan argumen seperti yang Anda harapkan muncul. Setiap argumen diwakili oleh satu atau lebih karakter dalam format string sebagai berikut.

static PyObject *module_func(PyObject *self, PyObject *args) {
   int i;
   double d;
   char *s;

   if (!PyArg_ParseTuple(args, "ids", &i, &d, &s)) {
      return NULL;
   }
   
   /* Do something interesting here. */
   Py_RETURN_NONE;
}

Mengkompilasi versi baru modul Anda dan mengimpornya memungkinkan Anda untuk memanggil fungsi baru dengan sejumlah argumen jenis apa pun −

module.func(1, s="three", d=2.0)
module.func(i=1, d=2.0, s="three")
module.func(s="three", d=2.0, i=1)

Anda mungkin dapat membuat lebih banyak variasi.

PyArg_ParseTuple Fungsi

Berikut adalah tanda tangan standar untuk PyArg_ParseTuple fungsi

int PyArg_ParseTuple(PyObject* tuple,char* format,...)

Fungsi ini mengembalikan 0 untuk kesalahan, dan nilai yang tidak sama dengan 0 untuk keberhasilan. tuple adalah PyObject* yang merupakan argumen kedua fungsi C. Berikut format adalah string C yang menjelaskan argumen wajib dan opsional.

Berikut adalah daftar kode format untuk PyArg_ParseTuple fungsi

Kode Tipe C Arti
c char String Python dengan panjang 1 menjadi karakter C.
d ganda Float Python menjadi double C.
f mengambang Apungan Python menjadi pelampung C.
i int Int Python menjadi int C.
l panjang Int Python menjadi panjang C.
L panjang panjang Int Python menjadi panjang C
O PyObject* Mendapatkan referensi pinjaman non-NULL untuk argumen Python.
s char* String python tanpa null yang disematkan ke karakter C*.
s# char*+int Semua string Python ke alamat dan panjang C.
t# char*+int Buffer segmen tunggal read-only ke alamat dan panjang C.
u Py_UNICODE* Python Unicode tanpa menyematkan null ke C.
u# Py_UNICODE*+int Alamat dan panjang Python Unicode C apa saja.
w# char*+int Baca/tulis buffer segmen tunggal ke alamat dan panjang C.
z char* Seperti s, juga menerima None (menyetel C char* ke NULL).
z# char*+int Seperti s#, juga menerima None (set C char* ke NULL).
(...) sesuai ... Urutan Python diperlakukan sebagai satu argumen per item.
Argumen berikut ini opsional.
Format akhir, diikuti dengan nama fungsi untuk pesan kesalahan.
Format berakhir, diikuti oleh seluruh teks pesan kesalahan.

Mengembalikan Nilai

Py_BuildValue mengambil format string seperti PyArg_ParseTuple melakukan. Alih-alih meneruskan alamat nilai yang Anda buat, Anda meneruskan nilai sebenarnya. Berikut adalah contoh yang menunjukkan cara menerapkan fungsi tambah −

static PyObject *foo_add(PyObject *self, PyObject *args) {
   int a;
   int b;

   if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
      return NULL;
   }
   return Py_BuildValue("i", a + b);
}

Beginilah jadinya jika diimplementasikan dengan Python

def add(a, b):
   return (a + b)

Anda dapat mengembalikan dua nilai dari fungsi Anda sebagai berikut, ini akan ditangkap menggunakan daftar dengan Python.

static PyObject *foo_add_subtract(PyObject *self, PyObject *args) {
   int a;
   int b;

   if (!PyArg_ParseTuple(args, "ii", &a, &b)) {
      return NULL;
   }
   return Py_BuildValue("ii", a + b, a - b);
}

Beginilah jadinya jika diimplementasikan dengan Python

def add_subtract(a, b):
   return (a + b, a - b)

Py_BuildValue Fungsi

Berikut adalah tanda tangan standar untuk Py_BuildValue fungsi

PyObject* Py_BuildValue(char* format,...)

Berikut format adalah string C yang menjelaskan objek Python untuk dibangun. Argumen berikut dari Py_BuildValue adalah nilai C dari mana hasilnya dibangun. PyObject* hasilnya adalah referensi baru.

Tabel berikut mencantumkan string kode yang umum digunakan, di mana nol atau lebih digabungkan ke dalam format string.

Kode Tipe C Arti
c char A C char menjadi string Python dengan panjang 1.
d ganda A C double menjadi float Python.
f mengambang Apungan C menjadi pelampung Python.
i int A C int menjadi Python int.
l panjang Panjang C menjadi int Python.
N PyObject* Meneruskan objek Python dan mencuri referensi.
O PyObject* Meneruskan objek Python dan memasukkannya seperti biasa.
O& convert+void* Konversi sewenang-wenang
s char* C 0-dihentikan char* ke string Python, atau NULL ke None.
s# char*+int C char* dan panjangnya ke string Python, atau NULL ke None.
u Py_UNICODE* C-wide, string diakhiri null ke Python Unicode, atau NULL ke None.
u# Py_UNICODE*+int String lebar-C dan panjang ke Python Unicode, atau NULL ke None.
w# char*+int Baca/tulis buffer segmen tunggal ke alamat dan panjang C.
z char* Seperti s, juga menerima None (menyetel C char* ke NULL).
z# char*+int Seperti s#, juga menerima None (menyetel C char* ke NULL).
(...) sesuai ... Membangun tupel Python dari nilai C.
[...] sesuai ... Membuat daftar Python dari nilai C.
{...} sesuai ... Membangun kamus Python dari nilai C, kunci dan nilai bergantian.

Kode {...} membangun kamus dari jumlah nilai C yang genap, secara bergantian kunci dan nilai. Misalnya, Py_BuildValue("{issi}",23,"zig","zag",42) mengembalikan kamus seperti {23:'zig','zag':42} Python.


Python

  1. Pemrograman Berorientasi Objek Python
  2. Pernyataan Python Print():Cara Mencetak dengan Contoh
  3. Python String strip() Fungsi dengan CONTOH
  4. Python String count() dengan CONTOH
  5. Format String Python() Jelaskan dengan CONTOH
  6. Metode Python String find() dengan Contoh
  7. Fungsi Python Lambda dengan CONTOH
  8. Python round() fungsi dengan CONTOH
  9. Python map() berfungsi dengan CONTOH
  10. Python Timeit() dengan Contoh