Halo semuanya. Saya memutuskan untuk sedikit menambah artikel C / C ++ dari Python .
Melewati tipe standar seperti int, bool, float, dan sebagainya cukup sederhana, tetapi tidak terlalu diperlukan. Python sendiri akan dengan cepat mengatasi data tersebut, dan tidak mungkin ada orang yang perlu mentransfer bagian dari kode tersebut ke pustaka C / C ++.
Tetapi transfer array data besar, atau bahkan array data dua dimensi yang lebih baik, atau bahkan array objek dua dimensi.
Semuanya di sini tidak begitu jelas, dan ada sejumlah hal yang saya pikir dapat disorot bagi mereka yang ingin secara signifikan mempercepat bagian kode yang sulit bagi juru bahasa python.
Contoh yang diberikan di bawah potongan tidak terlalu berguna untuk digunakan, tetapi saya pikir cukup untuk menyoroti semua nuansa prosedur ini.
Segera berikan kode sumber file perpustakaan.
py_list2c_array.h
#ifndef _PY_LIST_2_C_ARRAY_H_ #define _PY_LIST_2_C_ARRAY_H_ #include <stdio.h> typedef struct { int value; wchar_t* name; } Item; extern "C" __declspec(dllexport) int sum_diagonal(Item** field, size_t size); #endif
py_list2c_array.cpp
Semuanya juga standar di sini, kecuali saya perhatikan penggunaan fungsi wprintf () untuk mencetak baris seperti wchar_t * .
py_list2c_array.py
Dan sekarang yang paling penting. Saya akan memberikan kode sumber skrip python dengan deskripsi poin-poin penting.
import ctypes class PyItem: def __init__(self, value, name): self.value = value self.name = name class CItem(ctypes.Structure): _fields_ = [ ('value', ctypes.c_int), ('name', ctypes.c_wchar_p) ] def create_list(size): return [[PyItem(int(str(i+1)+str(j+1)), 'item{}{}'.format(i+1, j+1)) for j in range(size)] for i in range(size)] def py_list2c_array(py_list, size): rowType = CItem * size resultType = ctypes.POINTER(CItem) * size result = resultType() for i in range(size): row = rowType() for j in range(size): row[j] = CItem() row[j].value = py_list[i][j].value row[j].name = ctypes.c_wchar_p(py_list[i][j].name) result[i] = ctypes.cast(row, ctypes.POINTER(CItem)) return ctypes.cast(result, ctypes.POINTER(ctypes.POINTER(CItem))) if __name__ == '__main__': sLib = ctypes.cdll.LoadLibrary('./py_list2c_array.dll') size = 4 py_list = create_list(size) c_array = py_list2c_array(py_list, size) sLib.sum_diagonal.argtypes = [ctypes.POINTER(ctypes.POINTER(CItem)), ctypes.c_size_t] sLib.sum_diagonal.restype = ctypes.c_int result = sLib.sum_diagonal(c_array, ctypes.c_size_t(size)) print(': {}'.format(result))
Detail
Mari kita pertimbangkan beberapa fitur membuat array ctypes. Untuk melakukan ini, kita akan melihat lebih dekat fungsi mengonversi daftar ke array py_list2c_array. Anda harus menentukan jenisnya terlebih dahulu.
Jenis setiap baris dalam array didefinisikan sebagai jenis elemen dikalikan dengan jumlah elemen.
rowType = ukuran Item *
Tipe array didefinisikan sebagai tipe baris dari array dikalikan jumlah baris.
Saya akan menjelaskan sedikit di bawah ini tentang ctypes.POINTER (). ResultType = ctypes.POINTER (CItem) * ukuran
Selanjutnya, buat array yang dihasilkan .result = resultType ()
Dan dalam loop kita membuat setiap baris sebagai array satu dimensi .row = rowType ()
Selanjutnya, dalam loop bersarang, buat setiap elemen array dan berikan nilai pada struktur dari daftar objek python.row [j] = CItem ()
baris [j] .value = py_list [i] [j] .value
baris [j] .name = ctypes.c_wchar_p (py_list [i] [j] .name)
Kemudian setiap baris yang dibuat dengan elemen harus dikonversi ke jenis pointer ke array objek dan ditugaskan ke sel array yang dihasilkan.
Saya akan menulis tentang fungsi ctypes.cast () di bawah .result [i] = ctypes.cast (baris, ctypes.POINTER (CItem))
Dan tentu saja, konversikan seluruh array menjadi sebuah pointer. Kembalikan ctypes.cast (hasil, ctypes.POINTER (ctypes.POINTER (CItem))))
ctypes.POINTER
Ctypes memiliki ctypes.POINTER () - menunjukkan bahwa pointer sedang digunakan. Sebagai contoh: ctypes.POINTER (CItem) menunjukkan bahwa itu adalah pointer ke struktur CItem ().
Dengan demikian, dengan baris: ctypes.POINTER (ctypes.POINTER (CItem)) kita dapat menunjukkan bahwa itu adalah pointer ke pointer ke struktur CItem, atau di C ++ CItem ** A ada ctypes.pointer () . Fungsi ini mengembalikan pointer ke objek. Sebagai contoh: item = CItem ()
pointer = ctypes.pointer (item)
Mereka tidak boleh bingung, karena maknanya sama sekali berbeda.
ctypes.cast ()
Sekarang perhatikan fungsi ctypes.cast () yang sangat penting . Fungsi ini agak mirip dengan static_cast () dari C ++.
Hal ini memungkinkan Anda untuk membuat gips yang sangat penting.
Saat membuat jenis array, misalnya: rowType = CItem * 4
row = rowType ()
Dalam hal ini, baris adalah area memori dari 4 elemen struktur CItem.
Tentu saja, dalam formulir ini, kami tidak akan dapat menggunakan data ini. Tetapi jika kita menggunakan fungsi cor pada mereka: array_pointer = ctypes.cast (baris, ctypes.POINTER (CItem))
Dalam hal ini, array_pointer sudah menjadi pointer ke area memori dengan 4 struktur CItem.
Parameter pertama menetapkan area memori yang dibuat dengan elemen array, dan parameter kedua menunjukkan tipe wilayah mana yang harus dikonversi. Nah, sepertinya menyoroti poin utama saat mentransfer data array menggunakan ctypes.
Saya harap artikel ini akan membantu Anda lebih cepat dan sepenuhnya menangani perpustakaan ctypes yang indah.