如何从Python扩展模块的C代码调用内置函数(或方法)?
我目前要完成的工作是调整Pythons itertools
模块函数combinations
,以对传递的iterable
进行排序,然后再创建组合,以对返回的组合进行排序.
What I currently want to accomplish is to tweak Pythons itertools
module function combinations
to sort the passed iterable
before creating combinations out of it with the goal of having the returned combinations sorted.
我是第一次使用Python扩展模块,到目前为止,我唯一的经验就是编写和编译类似于Python扩展模块的"Hello World",但是我希望我的整体编程经验能帮助您进行几次编程语言是我可以赖以成功应对这一挑战的坚实基础.
I am working on a Python extension module for the first time and my only experience up to now was to write and compile a "Hello World" like Python extension module, but I hope that my overall programming experience in a couple of programming languages is a solid enough foundation I can build upon to succeed on this challenge.
我知道有一个内置的Python函数sorted()
可以对传递给combinations
的可迭代对象进行排序,但是我不知道如何从扩展模块的C代码中调用它.
I know that there is a builtin Python function sorted()
which can sort the iterable passed to combinations
but I don't know how to call it from within the C code of the extension module.
我只是尝试编写iterable = sorted(iterable);
,但是即使模块已编译(带有警告),也无法通过ImportError: cgitertools.cpython-36m-x86_64-linux-gnu.so: undefined symbol: sorted
I have tried just to write iterable = sorted(iterable);
but even if the module compiles (with a warning) the import of the compiled module fails with ImportError: cgitertools.cpython-36m-x86_64-linux-gnu.so: undefined symbol: sorted
我的问题是:
如何从Python扩展模块的C代码中调用Python的内置方法(以
sorted()
为例)?
How to call the Pythons builtin method (using as example
sorted()
) from within C code of a Python extension module?
下面是我尝试过的所有细节以及为什么它不起作用:
Below all the details of what I have tried and why it didn't work:
combinations_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
combinationsobject *co;
Py_ssize_t n;
Py_ssize_t r;
PyObject *pool = NULL;
PyObject *iterable = NULL;
Py_ssize_t *indices = NULL;
Py_ssize_t i;
static char *kwargs[] = {"iterable", "r", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "On:combinations", kwargs,
&iterable, &r))
return NULL;
// iterable.sort(); doesn't work ... cgitertoolsmodule.c:2398:13: error: request for member ‘sort’ in something not a structure or union
// iterable.__sort__(); doesn't work either with same error
// COMPILES, but gives ERROR on import in Python:
iterable = sorted(iterable);
$ python3.6 cgitertoolsmodule-setup.py build
running build
running build_ext
building 'cgitertools' extension
gcc -pthread -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -fPIC -I/usr/local/include/python3.6m -c cgitertoolsmodule.c -o build/temp.linux-x86_64-3.6/cgitertoolsmodule.o
cgitertoolsmodule.c: In function ‘combinations_new’:
cgitertoolsmodule.c:2400:16: warning: implicit declaration of function ‘sorted’ [-Wimplicit-function-declaration]
iterable = sorted(iterable);
^
cgitertoolsmodule.c:2400:14: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
iterable = sorted(iterable);
^
gcc -pthread -shared build/temp.linux-x86_64-3.6/cgitertoolsmodule.o -o build/lib.linux-x86_64-3.6/cgitertools.cpython-36m-x86_64-linux-gnu.so
$ python3.6
Python 3.6.1 (default, Apr 18 2017, 23:00:41)
[GCC 5.4.1 20160904] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from cgitertools import combinations
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ImportError: cgitertools.cpython-36m-x86_64-linux-gnu.so: undefined symbol: sorted
您应该从内置函数中获取 sorted 函数,然后调用它:
You should get the sorted function out of the builtins and than call it:
PyObject *builtins = PyEval_GetBuiltins();
PyObject *sorted = PyDict_GetItemString(builtins , "sorted");
PyObject *sorted_list = PyEval_CallFunction(sorted, "(O)", iterable);
//... do something with the sorted_list
Py_DECREF(sorted_list);