我有一个C扩展模块,我想添加一些Python实用程序功能。有推荐的方法吗?
例如:
import my_module
my_module.super_fast_written_in_C()
my_module.written_in_Python__easy_to_maintain()
我主要对Python 2.x感兴趣。
答案 0 :(得分:7)
通常的做法是:mymod.py包含用Python编写的实用程序函数,并导入_mymod模块中的好东西,该模块用C编写并从_mymod.so或_mymod.pyd导入。例如,查看Python发行版中的... / Lib / csv.py。
答案 1 :(得分:5)
使用下划线为您的原生扩展名添加前缀。 然后,在Python中,创建一个包装器模块,该模块导入该本机扩展,并在其上添加一些其他非本机例程。
答案 2 :(得分:1)
现有答案描述了最常用的方法:它具有在已编译的C扩展不可用的平台上允许纯Python(或其他语言)实现的潜在优势(包括Jython和IronPython)。
然而,在少数情况下,将模块拆分为C层和Python层可能不值得提供一些在Python中比在C中更合理地编写的附加内容。例如,{{3} }(此时为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
而非临时字典作为PyRun_String
的名称空间。当然,除了PyRun_String
所需的def
和class
语句之外,还有更复杂的方法,但是,对于足够简单的情况,这种简单的方法实际上可能就足够了。