0

我有一个 C 扩展模块,我想向其中添加一些 Python 实用程序函数。有推荐的方法吗?

例如:

import my_module

my_module.super_fast_written_in_C()
my_module.written_in_Python__easy_to_maintain()

我主要对 Python 2.x 感兴趣。

4

3 回答 3

8

这样做的常用方法是:mymod.py 包含用 Python 编写的实用程序函数,并在 _mymod 模块中导入好东西,该模块用 C 编写并从 _mymod.so 或 _mymod.pyd 导入。例如,查看 Python 发行版中的 .../Lib/csv.py。

于 2009-06-18T16:00:29.697 回答
5

使用下划线为您的原生扩展添加前缀。然后,在 Python 中,创建一个包装器模块,用于导入该原生扩展并在其之上添加一些其他非原生例程。

于 2009-06-18T15:52:28.760 回答
1

现有答案描述了最常用的方法:它具有允许在编译后的 C 扩展不可用的平台(包括 Jython 和 IronPython)上实现纯 Python(或其他语言)的潜在优势。

然而,在少数情况下,可能不值得将模块拆分为 C 层和 Python 层,只是为了提供一些用 Python 编写的比用 C 更合理的附加功能。例如,gmpy(第 7113 行 ff 在此time),为了启用gmpy' 类型的实例的酸洗,使用:

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_Stringdefandclass语句更复杂的方法,但是,对于足够简单的情况,这种简单的方法实际上可能就足够了。

于 2009-06-19T00:59:43.303 回答