从Python

时间:2016-03-31 19:01:01

标签: python gcc static-libraries python-c-extension

让我们说我想从命令行使用gcc来编译Python的C扩展。我构建了这样的调用:

gcc -o applesauce.pyd -I C:/Python35/include -L C:/Python35/libs -l python35 applesauce.c

我注意到-I-L-l选项是绝对必要的,否则您将收到类似this的错误。这些命令告诉gcc在哪里查找头文件(-I),在哪里查找静态库(-L),以及实际使用的静态库(python35,它实际上是翻译的到libpython35.a)。

现在,显然很容易获得libsinclude目录(如果是您的机器),因为如果您不想要它们,它们永远不会改变。但是,我正在编写一个从命令行调用gcc的程序,其他人将使用。发生此调用的行看起来像这样:

from subprocess import call
import sys
filename = applesauce.c
include_directory = os.path.join(sys.exec_prefix, 'include')
libs_directory = os.path.join(sys.exec_prefix, 'libs')

call(['gcc', ..., '-I', include_direcory, '-L', libs_directory, ...])

但是,其他人将拥有不同的平台和不同的Python安装结构,因此只需加入路径就不会有效。

相反,我需要一个来自Python 的解决方案,它将可靠地返回includelibs目录。

编辑:

我查看了模块distutils.ccompiler,发现了许多有用的函数,它们部分地使用了distutils,但是让我可以自定义我的编译器完全跨平台。唯一的问题是,我需要传递包含和运行时库...

编辑2:

我看了distutils.sysconfig我能够可靠地返回“包含”字样。目录包括所有头文件。我仍然不知道如何获取运行时库。

distutils.ccompiler个文档为here

需要此功能的程序名为Cyther

2 个答案:

答案 0 :(得分:5)

编译扩展程序的最简单方法是使用distutilslike this;

from distutils.core import setup
from distutils.extension import Extension
setup(name='foobar',
      version='1.0',
      ext_modules=[Extension('foo', ['foo.c'])],
      )

请记住,与unix / linux相比,compiling extensions on ms-windows is not straightforward因为ms编译器的不同版本与相应的C库紧密耦合。因此,在ms-windows上,您必须使用编译Python x.y的相同编译器编译Python x.y的扩展。这意味着使用旧的和不受支持的工具,例如Python 2.7,3.3和3.4。使用Python 3.5,情况正在发生变化(part 1part 2

修改 更多地研究了这个问题,我怀疑你想要的是100%可实现的。鉴于编译和链接所需的工具按照定义在Python之外,并且它们甚至不一定是Python编译的工具,syssysconfig中的信息无法保证准确实际安装Python的系统的表示形式。例如。大多数ms-windows机器都没有安装开发人员工具。甚至在POSIX平台上,安装的C编译器和构建Python的编译器之间可能存在差异,尤其是当它作为二进制包安装时。

答案 1 :(得分:1)

如果您在方法distutils中查看来自finalize_options的{​​{3}}来源,您会找到用于定位lib的不同平台的代码。