频道栏目
首页 > 资讯 > Python 解释器 扩展和嵌入 > 正文

3. 用distutils来构建C/C++扩展 Python 解释器 扩展和嵌入

16-01-11        来源:[db:作者]  
收藏   我要投稿
从Python 1.4开始,在Unix上,Python提供了一个特殊的makefile以产生一些makefile,使用这些产生的makefile可以构建动态链接的扩展和客制化的解释器。从Python 2.0开始,这个机制(即Makefile.pre.in和Setup文件)不再支持。构建客制化的解释器极少被应用,而扩展模块可以由distutils来构建。

使用distutils构建扩展模块需要构建机器上安装distutils。Python 2.x中都包含distutils,且从1.5开始,distutils就独立可用了。因为distutils也支持二进制包的创建,用户并不一定需要一个编译器和其他的分发工具来安装扩展。

一个distutils包包含一个驱动脚本,setup.py这只是一个Python文件,在最简单的情况下,看起来像这个样子:

from distutils.core import setup, Extension

module1 = Extension('demo',
                    sources = ['demo.c'])

setup (name = 'PackageName',
       version = '1.0',
       description = 'This is a demo package',
       ext_modules = [module1])

使用setup.py及文件demo.c,运行这个命令

python setup.py build 

将会编译demo.c,并在build目录下产生名为demo的扩展模块。依赖于构建系统,模块文件可能会在build/lib.system目录,名字可能是demo.so或者demo.pyd

setup.py中,所有的操作都是通过调用setup函数来执行的。这个函数有一组关键字参数,上面的例子只使用了其中的一个子集。特定地,例子中指明了用来构建包的元信息,也指明了包的内容。一般来说,包还会包含额外的模块,比如Python源文件模块,文档和子包等等。请参考Distributing Python Modules中distutils文档以了解关于distutils功能的更多信息。这一章节只解释如何构建扩展模块。

为了更好的结构化驱动脚本,通用的一个做法就是预先计算setup()的参数。在上面的例子中,setup()的参数ext_modules是一个扩展模块的列表,每一个扩展模块都是Extension的一个实例。在例子中,实例定义了一个名为demo的扩展,它通过编译单一源文件demo.c得到。

许多情况下,构建一个扩展要更复杂些,因为需要额外的预处理器定义和库。下面的例子演示了这种复杂的情况。

from distutils.core import setup, Extension

module1 = Extension('demo',
                    define_macros = [('MAJOR_VERSION', '1'),
                                     ('MINOR_VERSION', '0')],
                    include_dirs = ['/usr/local/include'],
                    libraries = ['tcl83'],
                    library_dirs = ['/usr/local/lib'],
                    sources = ['demo.c'])

setup (name = 'PackageName',
       version = '1.0',
       description = 'This is a demo package',
       author = 'Martin v. Loewis',
       author_email = 'martin@v.loewis.de',
       url = 'http://docs.python.org/extending/building',
       long_description = '''
This is really just a demo package.
''',
       ext_modules = [module1])

在这个例子中,setup()有额外的元信息,当构建分发包的时候推荐使用这些元信息。对于扩展,它指明了预处理器定义,头文件目录,库目录及库。distutils会把这些信息传递给编译器,具体的方式依系统而不同。例如在Unix上,这会产生如下的编译命令。

gcc -DNDEBUG -g -O3 -Wall -Wstrict-prototypes -fPIC -DMAJOR_VERSION=1 -DMINOR_VERSION=0 -I/usr/local/include -I/usr/local/include/python2.2 -c demo.c -o build/temp.linux-i686-2.2/demo.o gcc -shared build/temp.linux-i686-2.2/demo.o -L/usr/local/lib -ltcl83 -o build/lib.linux-i686-2.2/demo.so 

上面的编译命令只是用来演示;distutils用户应该相信distutils会得到正确的调用。

3.1. 分发你的扩展模块

当成功构建一个扩展后,有三种方法来使用它。

最终用户典型地希望安装这个模块,通过执行命令

python setup.py install 

模块的维护者想产生源码包,通过执行命令

python setup.py sdist 

在一些情况下,在源代码分发中需要包含额外的文件;这是通过MANIFEST.in文件来完成的; 参见distutils文档以得到详细信息。

如果已经成功构建了源代码分发,维护者还能创建二进制分发。依赖于不同的平台,执行下列命令中的某一个。

python setup.py bdist_wininst python setup.py bdist_rpm python setup.py bdist_dumb
相关TAG标签
上一篇:4. Building C and C++ Extensions on Windows Python 解释器 扩展和嵌入
下一篇:2. Defining New Types Python 解释器 扩展和嵌入
相关文章
图文推荐

关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 举报中心

版权所有: 红黑联盟--致力于做实用的IT技术学习网站