我有一个C扩展模块,我想添加一些Python实用程序功能。有推荐的方法吗?

例如:

import my_module

my_module.super_fast_written_in_C()
my_module.written_in_Python__easy_to_maintain()

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

有帮助吗?

解决方案

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

其他提示

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

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

然而,在少数情况下,将模块拆分为C层和Python层可能不值得提供一些在Python中比在C中更合理地编写的附加内容。例如, gmpy (此时为7113行),按顺序排列要启用 gmpy 类型实例的pickle,请使用:

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 而不是transient dictionary作为 PyRun_String 的命名空间。当然,除了 defRun_String def class 语句之外,还有更复杂的方法,但是,对于简单的情况,这种简单的方法实际上可能就足够了。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top