【问题标题】:How to call a builtin function (or method) from C code of a Python extension module?如何从 Python 扩展模块的 C 代码中调用内置函数(或方法)?
【发布时间】:2017-09-27 23:35:48
【问题描述】:

我目前想要完成的是调整 Pythons itertools 模块函数 combinations 以在创建组合之前对传递的 iterable 进行排序,目标是对返回的组合进行排序。

我是第一次做 Python 扩展模块,到目前为止我唯一的经验是编写和编译一个类似于 Python 扩展模块的“Hello World”,但我希望我在几个编程中的整体编程经验语言是一个足够坚实的基础,我可以在此基础上成功应对这一挑战。

我知道有一个内置的 Python 函数 sorted() 可以对传递给 combinations 的迭代进行排序,但我不知道如何从扩展模块的 C 代码中调用它。

我只是尝试写iterable = sorted(iterable);,但即使模块编译(带有警告),编译模块的导入也会失败并显示ImportError: cgitertools.cpython-36m-x86_64-linux-gnu.so: undefined symbol: sorted

我的问题是:

如何在 Python 扩展模块的 C 代码中调用 Python 的内置方法(以 sorted() 为例)?

下面是我尝试过的所有细节以及为什么它不起作用:

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

【问题讨论】:

    标签: python c python-3.x itertools extension-modules


    【解决方案1】:

    您应该从内置函数中获取 sorted 函数,然后调用它:

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

    【讨论】:

    • 你能解释一下“(0)”是什么意思吗?
    • 它是函数的参数格式,在这种情况下 - 一个位置参数是一个 PyObject
    猜你喜欢
    • 1970-01-01
    • 2010-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-23
    • 2014-10-19
    • 1970-01-01
    相关资源
    最近更新 更多