Artikel terakhir dalam seri tentang cara menjalankan C / C ++ dari Python3 membahas semua cara yang diketahui untuk melakukan ini. Kali ini saya harus meningkatkan . Apa yang terjadi dari ini baca di bawah.
C
Saya mengambil contoh yang sama dari perpustakaan tes sebagai dasar dan menjadikannya variasi untuk metode tertentu. Pustaka uji untuk mendemonstrasikan bekerja dengan variabel global, struktur, dan fungsi dengan argumen dari berbagai jenis.
test.c:
#include "test.hpp" int a = 5; double b = 5.12345; char c = 'X'; int func_ret_int(int val) { printf("C get func_ret_int: %d\n", val); return val; } double func_ret_double(double val) { printf("C get func_ret_double: %f\n", val); return val; } object func_ret_str(char *val) { printf("C get func_ret_str: %s\n", val); return object(string(val)); } char func_many_args(int val1, double val2, char val3, short val4) { printf("C get func_many_args: int - %d, double - %f, char - %c, short - %d\n", val1, val2, val3, val4); return val3; } test_st_t * func_ret_struct(test_st_t *test_st) { if (test_st) { printf("C get test_st: val1 - %d, val2 - %f, val3 - %c\n", test_st->val1, test_st->val2, test_st->val3); } return test_st; }
test.h:
using namespace boost::python; using namespace std; #ifdef __cplusplus extern "C" { #endif typedef struct test_st_s test_st_t; typedef char * char_p; extern int a; extern double b; extern char c; int func_ret_int(int val); double func_ret_double(double val); object func_ret_str(char *val); char func_many_args(int val1, double val2, char val3, short val4); test_st_t *func_ret_struct(test_st_t *test_st); struct test_st_s { int val1; double val2; char val3; }; #ifdef __cplusplus } #endif
Cara mengompilasi:
g++ -g -fPIC -I/usr/include/python3.6 -I./src/c -o ./objs/test.o -c ./src/c/test.cpp g++ -fPIC -g -shared -o ./lib/_test.so ./objs/test.o -lboost_python3
Sumber mengkompilasi ke perpustakaan dinamis.
python boost mirip dengan yang digunakan pada pybind11 , Anda juga perlu menjelaskan fungsi-fungsi yang akan dilihat python. Tapi menurut saya, meningkatkan lebih besar dan rumit. Sebagai contoh:
def("func_ret_struct", &func_ret_struct, return_value_policy<reference_existing_object>());
Fungsi func_ret_struct mengambil sebagai argumen penunjuk ke struktur dan mengembalikan penunjuk yang sama kembali. Untuk itu, Anda perlu menentukan aturan objek yang dikembalikan return_value_policy <reference_existing_object> () . reference_existing_objec mengatakan bahwa objek yang dikembalikan sudah ada. Jika Anda menentukan manage_new_object, itu berarti kami mengembalikan objek baru. Dalam hal ini, skrip tersebut akan jatuh ke dalam segmentasi kesalahan pada pengumpul sampah:
test_st = _test.test_st_t() ret = _test.func_ret_struct(test_st)
Karena pengumpul sampah pertama-tama akan menghapus data yang berisi test_st, dan kemudian ingin menghapus data yang berisi objek ret. Yang berisi data yang sama dengan test_st yang terkandung, tetapi sudah dihapus.
Sangat menarik bagaimana dalam hal ini untuk menggambarkan fungsi seperti itu (tidak masuk terlalu dalam)?:
test_st_t * func_ret_struct(test_st_t *test_st) { if (test_st) { return test_st; } else { return (test_st_t *) malloc(sizeof(test_st_t)); } }
Fungsi seperti itu dapat mengembalikan objek yang ada maupun yang sudah ada.
Saya juga punya masalah dengan fungsi seperti itu:
char * func_ret_str(char *val) { return val; }
Seperti yang saya pahami, Anda tidak bisa mendapatkan pointer ke tipe data standar dari python di boost. Itu hanya mungkin pada struct , kelas dan gabungan . Jika ada yang tahu cara untuk mencerahkan.
Python
Untuk python, modul menjadi asli.
main.py:
Pro dan kontra dorongan
Pro :
- sintaksis sederhana ketika digunakan dalam Python
Cons :
- Anda perlu mengedit sumber C ++, atau menulis ikatan untuknya
- meningkatkan saja tidak mudah
Kodenya, seperti biasa, saya coba komentari dengan jelas.
Waktu pelaksanaan pengujian rata-rata pada setiap metode dengan 1000 dimulai:
- ctypes: - 0,0004987692832946777 detik ---
- CFFI: - 0,00038521790504455566 detik ---
- pybind: - 0,0004547207355499268 detik ---
- API C: - 0,00035619735717773444 detik ---
- boost: - 0,00037789344787597656 detik ---
Referensi