4.构建C和C ++扩展 – 扩展和嵌入Python解释器(Python教程)(参考资料)
4.构建C和C ++扩展
CPython的AC扩展是一个共享库(例如Linux上的.so
文件,Windows上的.pyd
),它导出initialization function.
要导入,共享库必须在PYTHONPATH
上可用,并且必须以模块名称命名,并带有适当的扩展名。使用distutils时,会自动生成正确的文件名.
初始化函数有签名:
- PyObject *
PyInit_modulename
( void )
它返回一个完全 -初始化模块,或PyModuleDef
实例。参见初始化C模块了解详情.
对于只有ASCII名称的模块,该函数必须命名为PyInit_<modulename>
,并带有<modulename>
替换为了模块的名称。当使用多阶段初始化时,允许使用非ASCII模块名称。在这种情况下,初始化函数名称为PyInitU_<modulename>
,其中<modulename>
使用Python的punycode编码进行编码,连字符替换为下划线。在Python中:
def initfunc_name(name):
try:
suffix = b'_' + name.encode('ascii')
except UnicodeEncodeError:
suffix = b'U_' + name.encode('punycode').replace(b'-', b'_')
return b'PyInit' + suffix
通过定义多个初始化函数,可以从单个共享库中导出多个模块。但是,导入它们需要使用符号链接或自定义导入器,因为默认情况下只找到与文件名对应的功能。请参阅“Multiple modules in one library”部分 PEP 489 了解详情.
4.1。使用distutils构建C和C ++扩展
可以使用distutils构建扩展模块,distutils包含在Python中。由于distutils还支持创建二进制包,用户不一定需要编译器和distutils来安装扩展。
distutils包中包含一个驱动脚本setup.py
。这是一个plainPython文件,在最简单的情况下,它看起来像这样:
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])
python setup.py build
将编译demo.c
,并在demo
目录中生成一个名为build
的扩展模块。根据系统的不同,模块文件将在一个子目录build/lib.system
中结束,并且可能具有类似demo.so
或demo.pyd
.
在setup.py
中,所有执行都是通过调用setup
功能。这需要可变数量的关键字参数,上面的示例仅使用子集。具体来说,该示例指定了构建包的信息,并指定了包的内容。通常,包将包含其他模块,如Pythonsource模块,文档,子包等。请参考分发Python模块(旧版)了解更多关于distutils的特点;本节仅介绍构建扩展模块.
通常预先计算setup()
,以更好地构造驱动程序脚本。在上面的例子中,ext_modules
的setup()
参数是一个扩展模块列表,每个扩展模块都是Extension
。在这个例子中,instance定义了一个名为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 = '[email protected]',
url = 'https://docs.python.org/extending/building',
long_description = '''
This is really just a demo package.
''',
ext_modules = [module1])
在这个例子中,setup()
使用additionalmeta-information调用,这是在建立分发包时建议的。对于extensionitself,它指定预处理器定义,包括目录,库目录和库。根据编译器的不同,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
评论被关闭。