四时宝库

程序员的知识宝库

教你创建 Python的 C语言 扩展(python拓展c)


在本教程中,我们将了解如何使用C编程语言创建一个非常简单的 Python 模块。我觉得这是一个很好的话题,因为我个人很难找到有效的简洁文档并向我展示了基础知识。

为什么需要 C 扩展?

C在 Python 语言成为瓶颈的情况下,能够编写扩展程序会派上用场。有时您需要低级语言的原始性能,例如C为了减少响应时间和处理时间等。

基本要求

在本教程中,我们将构建一个非常简单的C基于 Python 的模块,该模块将具有许多不同的功能,希望这些功能足以让您入门。

我们将创建 2 个不同的函数:

  • 一个Hello World简单地执行打印的函数。
  • 一个接收值的简单斐波那契函数n。

入门

让我们深入研究C代码。打开.c将包含新模块的文件并添加#include <Python.h>到顶部。这将引入必要的CPython 对象,使我们能够构建我们的模块。

#include <Python.h>

// Function 1: A simple 'hello world' function
static PyObject* helloworld(PyObject* self, PyObject* args)
{
    printf("Hello World\n");
    return Py_None;
}

// Our Module's Function Definition struct
// We require this `NULL` to signal the end of our method
// definition
static PyMethodDef myMethods[] = {
    { "helloworld", helloworld, METH_NOARGS, "Prints Hello World" },
    { NULL, NULL, 0, NULL }
};

// Our Module Definition struct
static struct PyModuleDef myModule = {
    PyModuleDef_HEAD_INIT,
    "myModule",
    "Test Module",
    -1,
    myMethods
};

// Initializes our module using our above struct
PyMODINIT_FUNC PyInit_myModule(void)
{
    return PyModule_Create(&myModule);
}

我们的 setup.py 文件

值得庆幸的是,Python 包含一些使语言扩展更容易的模块。在这里,我们可以指定我们模块的名称并传入.c组成我们模块的必要文件。

from distutils.core import setup, Extension
setup(name = 'myModule', version = '1.0',  \
   ext_modules = [Extension('myModule', ['test.c'])])

构建和安装我们的模块

为了build和install我们新创建的C模块,我们必须执行以下操作:

python setup.py build
python setup.py install

连续运行时,您应该看到以下输出。然后我们可以启动我们的 Python 解释器并调用我们新创建的模块:

 $ python3.6 setup.py build
running build
running build_ext
building 'myModule' extension
/usr/bin/clang -fno-strict-aliasing -Wsign-compare -fno-common -dynamic -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -arch i386 -arch x86_64 -g -I/Library/Frameworks/Python.framework/Versions/3.6/include/python3.6m -c test.c -o build/temp.macosx-10.6-intel-3.6/test.o
/usr/bin/clang -bundle -undefined dynamic_lookup -arch i386 -arch x86_64 -g build/temp.macosx-10.6-intel-3.6/test.o -o build/lib.macosx-10.6-intel-3.6/myModule.cpython-36m-darwin.so

 $ python3.6 setup.py install
running install
running build
running build_ext
running install_lib
copying build/lib.macosx-10.6-intel-3.6/myModule.cpython-36m-darwin.so -> /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages
running install_egg_info
Removing /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/myModule-1.0-py3.6.egg-info
Writing /Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/myModule-1.0-py3.6.egg-info

 $ python3.6
Python 3.6.0 (v3.6.0:41df79263a11, Dec 22 2016, 17:23:13)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import myModule
>>> myModule.helloworld()
Hello World
>>>

我们的斐波那契函数

现在让我们看一个更复杂的函数,它接收一个值n ,然后返回适当的斐波那契数。我们不会在memoization这里做任何花哨的事情,它将是一个普通的旧递归函数,具有糟糕的性能。然而,它将向我们展示如何在我们的C模块中接收一个值并返回一个值。

// Function 2: A C fibonacci implementation
// this is nothing special and looks exactly
// like a normal C version of fibonacci would look
int Cfib(int n)
{
    if (n < 2)
        return n;
    else
        return Cfib(n-1)+Cfib(n-2);
}
// Our Python binding to our C function
// This will take one and only one non-keyword argument
static PyObject* fib(PyObject* self, PyObject* args)
{
    // instantiate our `n` value
    int n;
    // if our `n` value
    if(!PyArg_ParseTuple(args, "i", &n))
        return NULL;
    // return our computed fib number
    return Py_BuildValue("i", Cfib(n));
}

同样,我们应该像以前一样构建和安装它。然后我们可以像这样测试它:

>>> import myModule
>>> myModule.fib(2)
1

结论

希望您发现本教程很有用,它阐明了创建您自己的C基于模块的过程。如果您想留下一些反馈或提出其他问题,请随时在下面的评论部分中。


发表评论:

控制面板
您好,欢迎到访网站!
  查看权限
网站分类
最新留言
    友情链接