2009-06-18 2 views
0

У меня есть модуль расширения C, к которому я хотел бы добавить некоторые служебные функции Python. Есть ли рекомендуемый способ сделать это?Объединение функций C и Python в модуле

Например:

import my_module 

my_module.super_fast_written_in_C() 
my_module.written_in_Python__easy_to_maintain() 

Я в первую очередь заинтересованы в Python 2.x.

ответ

7

Обычный способ: mymod.py содержит функции утилиты, написанные на Python, и импортирует плюсы в модуле _mymod, который написан на C и импортируется из _mymod.so или _mymod.pyd. Например, посмотрите на .../Lib/csv.py в вашем дистрибутиве Python.

+0

csv.py - действительно полезный пример –

5

Префикс родного расширения с подчеркиванием. Затем, на Python, создайте модуль-оболочку, который импортирует это собственное расширение и добавит к нему некоторые другие неродственные подпрограммы.

1

В существующих ответах описывается наиболее часто используемый метод: у него есть потенциальное преимущество использования реализаций pure-Python (или другого языка) на платформах, в которых скомпилированное расширение C недоступно (включая Jython и IronPython).

В некоторых случаях, однако, может не стоить разделить модуль на С-слой и слой Python, чтобы предоставить несколько дополнительных функций, которые более разумно записаны на Python, чем в C. Например, gmpy (строки 7113 и далее в это время), с тем чтобы травление экземпляров типа gmpy «s, использует:

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); 

Если вы хотите, чтобы эти несколько дополнительных функций„остаться“в модуле (не обязательно в этом примере случай), вы, конечно же, будете использовать свой объект модуля, построенный по Py_InitModule3 (или каким-либо другим способом) и его PyModule_GetDict, а не временный словарь как пространство имен, в котором должно быть PyRun_String. И, конечно, есть более сложные подходы, чем PyRun_String, необходимые вам и class заявлениями, но для простых случаев этого простого подхода на самом деле может быть достаточно.

+0

Спасибо: Мне было интересно посмотреть, как это можно сделать, а также более общий путь. –

Смежные вопросы