Kombinieren C und Python Funktionen in einem Modul
Frage
Ich habe ein C-Erweiterungsmodul, an denen Ich mag würde einige Python Utility-Funktionen hinzuzufügen. Gibt es eine empfohlene Weg, dies zu tun?
Zum Beispiel:
import my_module
my_module.super_fast_written_in_C()
my_module.written_in_Python__easy_to_maintain()
Ich bin in erster Linie interessiert in Python 2.x.
Lösung
Der üblicher Weg, dies zu tun ist: mymod.py enthält die Utility-Funktionen in Python geschrieben und importiert die Leckereien in dem _mymod-Modul, das in C geschrieben ist und von _mymod.so oder _mymod.pyd importiert. Zum Beispiel, schaut ... / Lib / csv.py in Ihrer Python-Distribution.
Andere Tipps
Präfix Ihrer native Erweiterung mit einem Unterstrich. Dann in Python, erstellen Sie ein Wrapper-Modul, das die native Erweiterung importiert und fügt einige andere nicht-native Routinen obendrein.
Die bestehenden Antworten beschreiben das Verfahren am häufigsten verwendet. Das Potenzial Vorteil, dass pure-Python (oder andere-Sprache) Implementierungen auf Plattformen, in denen die kompilierte C-Erweiterung nicht verfügbar ist (einschließlich Jython und Ironpython)
In einigen Fällen kann es jedoch nicht wert sein, das Modul in eine C-Schicht spalten und eine Python-Schicht nur ein paar Extras zu schaffen, die als beispielsweise in C in Python sinnvoller geschrieben werden, gmpy (Zeilen 7113 ff zu diesem Zeitpunkt), um zu ermöglichen Beizen von Instanzen von gmpy
des Typs verwendet:
copy_reg_module = PyImport_ImportModule("copy_reg");
if (copy_reg_module) {
char* enable_pickle =
"def mpz_reducer(an_mpz): return (gmpy.mpz, (an_mpz.binary(), 256))\n"
"def mpq_reducer(an_mpq): return (gmpy.mpq, (an_mpq.binary(), 256))\n"
"def mpf_reducer(an_mpf): return (gmpy.mpf, (an_mpf.binary(), 0, 256))\n"
"copy_reg.pickle(type(gmpy.mpz(0)), mpz_reducer)\n"
"copy_reg.pickle(type(gmpy.mpq(0)), mpq_reducer)\n"
"copy_reg.pickle(type(gmpy.mpf(0)), mpf_reducer)\n"
;
PyObject* namespace = PyDict_New();
PyObject* result = NULL;
if (options.debug)
fprintf(stderr, "gmpy_module imported copy_reg OK\n");
PyDict_SetItemString(namespace, "copy_reg", copy_reg_module);
PyDict_SetItemString(namespace, "gmpy", gmpy_module);
PyDict_SetItemString(namespace, "type", (PyObject*)&PyType_Type);
result = PyRun_String(enable_pickle, Py_file_input,
namespace, namespace);
Wenn Sie diese paar zusätzlichen Funktionen „bleiben, um“ in Ihrem Modul (nicht notwendig, in diesem Beispielfall) wollen, können Sie natürlich würden Ihr Modul-Objekt verwenden, wie durch Py_InitModule3
gebaut (oder was auch immer andere Verfahren) und seine PyModule_GetDict
statt ein transienter Wörterbuch als Namensraum, in dem PyRun_String
. Und natürlich gibt es anspruchsvollere Ansätze als die PyRun_String
und def
Aussagen class
Sie brauchen, aber für einfache genug Fälle, dieser einfache Ansatz in der Tat ausreichend sein kann.