Files
hustoj/web/python-docs/extending/windows.html
2025-03-09 17:10:56 +08:00

305 lines
22 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="zh_CN">
<head>
<meta charset="utf-8" /><meta name="generator" content="Docutils 0.17.1: http://docutils.sourceforge.net/" />
<title>5. 在Windows平台编译C和C++扩展 &#8212; Python 3.8.20 文档</title><meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="../_static/pydoctheme.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script id="documentation_options" data-url_root="../" src="../_static/documentation_options.js"></script>
<script src="../_static/jquery.js"></script>
<script src="../_static/underscore.js"></script>
<script src="../_static/doctools.js"></script>
<script src="../_static/language_data.js"></script>
<script src="../_static/translations.js"></script>
<script src="../_static/sidebar.js"></script>
<link rel="search" type="application/opensearchdescription+xml"
title="在 Python 3.8.20 文档 中搜索"
href="../_static/opensearch.xml"/>
<link rel="author" title="关于这些文档" href="../about.html" />
<link rel="index" title="索引" href="../genindex.html" />
<link rel="search" title="搜索" href="../search.html" />
<link rel="copyright" title="版权所有" href="../copyright.html" />
<link rel="next" title="1. 在其它应用程序嵌入 Python" href="embedding.html" />
<link rel="prev" title="4. 构建C/C++扩展" href="building.html" />
<link rel="canonical" href="https://docs.python.org/3/extending/windows.html" />
<style>
@media only screen {
table.full-width-table {
width: 100%;
}
}
</style>
<link rel="shortcut icon" type="image/png" href="../_static/py.svg" />
<script type="text/javascript" src="../_static/copybutton.js"></script>
<script type="text/javascript" src="../_static/menu.js"></script>
</head>
<body>
<div class="mobile-nav">
<input type="checkbox" id="menuToggler" class="toggler__input" aria-controls="navigation"
aria-pressed="false" aria-expanded="false" role="button" aria-label="Menu" />
<label for="menuToggler" class="toggler__label">
<span></span>
</label>
<nav class="nav-content" role="navigation">
<a href="https://www.python.org/" class="nav-logo">
<img src="../_static/py.svg" alt="Logo"/>
</a>
<div class="version_switcher_placeholder"></div>
<form role="search" class="search" action="../search.html" method="get">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" class="search-icon">
<path fill-rule="nonzero"
d="M15.5 14h-.79l-.28-.27a6.5 6.5 0 001.48-5.34c-.47-2.78-2.79-5-5.59-5.34a6.505 6.505 0 00-7.27 7.27c.34 2.8 2.56 5.12 5.34 5.59a6.5 6.5 0 005.34-1.48l.27.28v.79l4.25 4.25c.41.41 1.08.41 1.49 0 .41-.41.41-1.08 0-1.49L15.5 14zm-6 0C7.01 14 5 11.99 5 9.5S7.01 5 9.5 5 14 7.01 14 9.5 11.99 14 9.5 14z" fill="#444"></path>
</svg>
<input type="text" name="q" aria-label="快速搜索"/>
<input type="submit" value="转向"/>
</form>
</nav>
<div class="menu-wrapper">
<nav class="menu" role="navigation" aria-label="main navigation">
<div class="language_switcher_placeholder"></div>
<h3><a href="../contents.html">目录</a></h3>
<ul>
<li><a class="reference internal" href="#">5. 在Windows平台编译C和C++扩展</a><ul>
<li><a class="reference internal" href="#a-cookbook-approach">5.1. 菜谱式说明</a></li>
<li><a class="reference internal" href="#differences-between-unix-and-windows">5.2. Unix 和 Windows 之间的差异</a></li>
<li><a class="reference internal" href="#using-dlls-in-practice">5.3. DLL 的实际使用</a></li>
</ul>
</li>
</ul>
<h4>上一个主题</h4>
<p class="topless"><a href="building.html"
title="上一章"><span class="section-number">4. </span>构建C/C++扩展</a></p>
<h4>下一个主题</h4>
<p class="topless"><a href="embedding.html"
title="下一章"><span class="section-number">1. </span>在其它应用程序嵌入 Python</a></p>
<div role="note" aria-label="source link">
<h3>本页</h3>
<ul class="this-page-menu">
<li><a href="../bugs.html">报告 Bug</a></li>
<li>
<a href="https://github.com/python/cpython/blob/3.8/Doc/extending/windows.rst"
rel="nofollow">显示源代码
</a>
</li>
</ul>
</div>
</nav>
</div>
</div>
<div id="outdated-warning" style="padding: .5em; text-align: center; background-color: #FFBABA; color: #6A0E0E;">
这个文档所针对的是一个已不再受支持的 Python 旧版本。
你应当升级版本,并阅读
<a href="/3/extending/windows.html"> Python 当前稳定版本的文档</a>.
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>导航</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="总目录"
accesskey="I">索引</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python 模块索引"
>模块</a> |</li>
<li class="right" >
<a href="embedding.html" title="1. 在其它应用程序嵌入 Python"
accesskey="N">下一页</a> |</li>
<li class="right" >
<a href="building.html" title="4. 构建C/C++扩展"
accesskey="P">上一页</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.8.20 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" accesskey="U">扩展和嵌入 Python 解释器</a> &#187;</li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
<input type="submit" value="转向" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
</ul>
</div>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="building-c-and-c-extensions-on-windows">
<span id="building-on-windows"></span><h1><span class="section-number">5. </span>在Windows平台编译C和C++扩展<a class="headerlink" href="#building-c-and-c-extensions-on-windows" title="永久链接至标题"></a></h1>
<p>这一章简要介绍了如何使用 Microsoft Visual C++ 创建 Python 的 Windows 扩展模块,然后再提供有关其工作机理的详细背景信息。 这些说明材料同时适用于 Windows 程序员学习构建 Python 扩展以及 Unix 程序员学习如何生成在 Unix 和 Windows 上均能成功构建的软件。</p>
<p>鼓励模块作者使用 distutils 方式来构建扩展模块,而不使用本节所描述的方式。 你仍将需要使用 C 编译器来构建 Python通常为 Microsoft Visual C++。</p>
<div class="admonition note">
<p class="admonition-title">注解</p>
<p>这一章提及了多个包括已编码 Python 版本号的文件名。 这些文件名以显示为 <code class="docutils literal notranslate"><span class="pre">XY</span></code> 的版本号来代表;在实践中,<code class="docutils literal notranslate"><span class="pre">'X'</span></code> 将为你所使用的 Python 发布版的主版本号而 <code class="docutils literal notranslate"><span class="pre">'Y'</span></code> 将为次版本号。 例如,如果你所使用的是 Python 2.2.1<code class="docutils literal notranslate"><span class="pre">XY</span></code> 将为 <code class="docutils literal notranslate"><span class="pre">22</span></code></p>
</div>
<section id="a-cookbook-approach">
<span id="win-cookbook"></span><h2><span class="section-number">5.1. </span>菜谱式说明<a class="headerlink" href="#a-cookbook-approach" title="永久链接至标题"></a></h2>
<p>在 Windows 和 Unix 上构建扩展模块都有两种方式:使用 <a class="reference internal" href="../library/distutils.html#module-distutils" title="distutils: Support for building and installing Python modules into an existing Python installation."><code class="xref py py-mod docutils literal notranslate"><span class="pre">distutils</span></code></a> 包来控制构建过程,或者全手动操作。 distutils 方式适用于大多数扩展;使用 <a class="reference internal" href="../library/distutils.html#module-distutils" title="distutils: Support for building and installing Python modules into an existing Python installation."><code class="xref py py-mod docutils literal notranslate"><span class="pre">distutils</span></code></a> 构建和打包扩展模块的文档见 <a class="reference internal" href="../distutils/index.html#distutils-index"><span class="std std-ref">分发 Python 模块(遗留版本)</span></a>。 如果你发现你确实需要手动操作,那么研究一下 <a class="reference external" href="https://github.com/python/cpython/tree/3.8/PCbuild/winsound.vcxproj">winsound</a> 标准库模块的项目文件可能会很有帮助。</p>
</section>
<section id="differences-between-unix-and-windows">
<span id="dynamic-linking"></span><h2><span class="section-number">5.2. </span>Unix 和 Windows 之间的差异<a class="headerlink" href="#differences-between-unix-and-windows" title="永久链接至标题"></a></h2>
<p>Unix 和 Windows 对于代码的运行时加载使用了完全不同的范式。 在你尝试构建可动态加载的模块之前,要先了解你所用系统是如何工作的。</p>
<p>在 Unix 中,一个共享对象 (<code class="file docutils literal notranslate"><span class="pre">.so</span></code>) 文件中包含将由程序来使用的代码,也包含在程序中可被找到的函数名称和数据。 当文件被合并到程序中时,对在文件代码中这些函数和数据的全部引用都会被改为指向程序中函数和数据在内存中所放置的实际位置。 这基本上是一个链接操作。</p>
<p>在 Windows 中,一个动态链接库 (<code class="file docutils literal notranslate"><span class="pre">.dll</span></code>) 文件中没有悬挂的引用。 而是通过一个查找表执行对函数或数据的访问。 因此在运行时 DLL 代码不必在运行时进行修改;相反地,代码已经使用了 DLL 的查找表,并且在运行时查找表会被修改以指向特定的函数和数据。</p>
<p>在 Unix 中,只存在一种库文件 (<code class="file docutils literal notranslate"><span class="pre">.a</span></code>),它包含来自多个对象文件 (<code class="file docutils literal notranslate"><span class="pre">.o</span></code>) 的代码。 在创建共享对象文件 (<code class="file docutils literal notranslate"><span class="pre">.so</span></code>) 的链接阶段,链接器可能会发现它不知道某个标识符是在哪里定义的。 链接器将在各个库的对象文件中查找它;如果找到了它,链接器将会包括来自该对象文件的所有代码。</p>
<p>在 Windows 中,存在两种库类型,静态库和导入库 (扩展名都是 <code class="file docutils literal notranslate"><span class="pre">.lib</span></code>)。 静态库类似于 Unix 的 <code class="file docutils literal notranslate"><span class="pre">.a</span></code> 文件;它包含在必要时可被包括的代码。 导入库基本上仅用于让链接器能确保特定标识符是合法的,并且将在 DLL 被加载时出现于程序中。 这样链接器可使用来自导入库的信息构建查找表以便使用未包括在 DLL 中的标识符。 当一个应用程序或 DLL 被链接时,可能会生成一个导入库,它将需要被用于应用程序或 DLL 中未来所有依赖于这些符号的 DLL。</p>
<p>假设你正在编译两个动态加载模块 B 和 C它们应当共享另一个代码块 A。 在 Unix 上,你 <em>不应</em><code class="file docutils literal notranslate"><span class="pre">A.a</span></code> 传给链接器作为 <code class="file docutils literal notranslate"><span class="pre">B.so</span></code><code class="file docutils literal notranslate"><span class="pre">C.so</span></code>;那会导致它被包括两次,这样 B 和 C 将分别拥有它们自己的副本。 在 Windows 上,编译 <code class="file docutils literal notranslate"><span class="pre">A.dll</span></code> 将同时编译 <code class="file docutils literal notranslate"><span class="pre">A.lib</span></code>。 你 <em>应当</em><code class="file docutils literal notranslate"><span class="pre">A.lib</span></code> 传给链接器用于 B 和 C。 <code class="file docutils literal notranslate"><span class="pre">A.lib</span></code> 并不包含代码;它只包含将在运行时被用于访问 A 的代码的信息。</p>
<p>在 Windows 上,使用导入库有点像是使用 <code class="docutils literal notranslate"><span class="pre">import</span> <span class="pre">spam</span></code>;它让你可以访问 spam 中的名称,但并不会创建一个单独副本。 在 Unix 上,链接到一个库更像是 <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">spam</span> <span class="pre">import</span> <span class="pre">*</span></code>;它会创建一个单独副本。</p>
</section>
<section id="using-dlls-in-practice">
<span id="win-dlls"></span><h2><span class="section-number">5.3. </span>DLL 的实际使用<a class="headerlink" href="#using-dlls-in-practice" title="永久链接至标题"></a></h2>
<p>Windows 版 Python 是用 Microsoft Visual C++ 编译的;使用其他编译器可能行也可能不行(但 Borland 看来是可以的)。 这一节的剩余部分只适用于 MSVC++。</p>
<p>当在 Windows 中创建 DLL 时,你必须将 <code class="file docutils literal notranslate"><span class="pre">pythonXY.lib</span></code> 传给链接器。 要编译两个 DLLspam 和 ni (会使用 spam 中找到的 C 函数),你应当使用以下命令:</p>
<div class="highlight-c notranslate"><div class="highlight"><pre><span></span><span class="n">cl</span><span class="w"> </span><span class="o">/</span><span class="n">LD</span><span class="w"> </span><span class="o">/</span><span class="n">I</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="n">include</span><span class="w"> </span><span class="n">spam</span><span class="p">.</span><span class="n">c</span><span class="w"> </span><span class="p">..</span><span class="o">/</span><span class="n">libs</span><span class="o">/</span><span class="n">pythonXY</span><span class="p">.</span><span class="n">lib</span>
<span class="n">cl</span><span class="w"> </span><span class="o">/</span><span class="n">LD</span><span class="w"> </span><span class="o">/</span><span class="n">I</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="n">include</span><span class="w"> </span><span class="n">ni</span><span class="p">.</span><span class="n">c</span><span class="w"> </span><span class="n">spam</span><span class="p">.</span><span class="n">lib</span><span class="w"> </span><span class="p">..</span><span class="o">/</span><span class="n">libs</span><span class="o">/</span><span class="n">pythonXY</span><span class="p">.</span><span class="n">lib</span>
</pre></div>
</div>
<p>第一个命令创建了三个文件: <code class="file docutils literal notranslate"><span class="pre">spam.obj</span></code>, <code class="file docutils literal notranslate"><span class="pre">spam.dll</span></code><code class="file docutils literal notranslate"><span class="pre">spam.lib</span></code><code class="file docutils literal notranslate"><span class="pre">Spam.dll</span></code> 不包含任何 Python 函数 (例如 <a class="reference internal" href="../c-api/arg.html#c.PyArg_ParseTuple" title="PyArg_ParseTuple"><code class="xref c c-func docutils literal notranslate"><span class="pre">PyArg_ParseTuple()</span></code></a>),但它通过 <code class="file docutils literal notranslate"><span class="pre">pythonXY.lib</span></code> 可以知道如何找到所需的 Python 代码。</p>
<p>第二条命令创建了 <code class="file docutils literal notranslate"><span class="pre">ni.dll</span></code> (以及 <code class="file docutils literal notranslate"><span class="pre">.obj</span></code><code class="file docutils literal notranslate"><span class="pre">.lib</span></code>),它知道如何从 spam 以及 Python 可执行文件中找到所需的函数。</p>
<p>不是每个标识符都会被导出到查找表。 如果你想要任何其他模块(包括 Python都能看到你的标识符你必须写上 <code class="docutils literal notranslate"><span class="pre">_declspec(dllexport)</span></code>,就如在 <code class="docutils literal notranslate"><span class="pre">void</span> <span class="pre">_declspec(dllexport)</span> <span class="pre">initspam(void)</span></code><code class="docutils literal notranslate"><span class="pre">PyObject</span> <span class="pre">_declspec(dllexport)</span> <span class="pre">*NiGetSpamData(void)</span></code> 中一样。</p>
<p>Developer Studio 将加入大量你并不真正需要的导入库,使你的可执行文件大小增加 100K。 要摆脱它们,请使用项目设置对话框的链接选项卡指定 <em>忽略默认库</em>。 将正确的 <code class="file docutils literal notranslate"><span class="pre">msvcrtxx.lib</span></code> 添加到库列表中。</p>
</section>
</section>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<h3><a href="../contents.html">目录</a></h3>
<ul>
<li><a class="reference internal" href="#">5. 在Windows平台编译C和C++扩展</a><ul>
<li><a class="reference internal" href="#a-cookbook-approach">5.1. 菜谱式说明</a></li>
<li><a class="reference internal" href="#differences-between-unix-and-windows">5.2. Unix 和 Windows 之间的差异</a></li>
<li><a class="reference internal" href="#using-dlls-in-practice">5.3. DLL 的实际使用</a></li>
</ul>
</li>
</ul>
<h4>上一个主题</h4>
<p class="topless"><a href="building.html"
title="上一章"><span class="section-number">4. </span>构建C/C++扩展</a></p>
<h4>下一个主题</h4>
<p class="topless"><a href="embedding.html"
title="下一章"><span class="section-number">1. </span>在其它应用程序嵌入 Python</a></p>
<div role="note" aria-label="source link">
<h3>本页</h3>
<ul class="this-page-menu">
<li><a href="../bugs.html">报告 Bug</a></li>
<li>
<a href="https://github.com/python/cpython/blob/3.8/Doc/extending/windows.rst"
rel="nofollow">显示源代码
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="related" role="navigation" aria-label="related navigation">
<h3>导航</h3>
<ul>
<li class="right" style="margin-right: 10px">
<a href="../genindex.html" title="总目录"
>索引</a></li>
<li class="right" >
<a href="../py-modindex.html" title="Python 模块索引"
>模块</a> |</li>
<li class="right" >
<a href="embedding.html" title="1. 在其它应用程序嵌入 Python"
>下一页</a> |</li>
<li class="right" >
<a href="building.html" title="4. 构建C/C++扩展"
>上一页</a> |</li>
<li><img src="../_static/py.svg" alt="python logo" style="vertical-align: middle; margin-top: -1px"/></li>
<li><a href="https://www.python.org/">Python</a> &#187;</li>
<li class="switchers">
<div class="language_switcher_placeholder"></div>
<div class="version_switcher_placeholder"></div>
</li>
<li>
</li>
<li id="cpython-language-and-version">
<a href="../index.html">3.8.20 Documentation</a> &#187;
</li>
<li class="nav-item nav-item-1"><a href="index.html" >扩展和嵌入 Python 解释器</a> &#187;</li>
<li class="right">
<div class="inline-search" role="search">
<form class="inline-search" action="../search.html" method="get">
<input placeholder="快速搜索" aria-label="快速搜索" type="text" name="q" />
<input type="submit" value="转向" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
|
</li>
</ul>
</div>
<div class="footer">
&copy; <a href="../copyright.html">版权所有</a> 2001-2024, Python Software Foundation.
<br />
This page is licensed under the Python Software Foundation License Version 2.
<br />
Examples, recipes, and other code in the documentation are additionally licensed under the Zero Clause BSD License.
<br />
<br />
The Python Software Foundation is a non-profit corporation.
<a href="https://www.python.org/psf/donations/">Please donate.</a>
<br />
<br />
最后更新于 12月 09, 2024.
<a href="https://docs.python.org/3/bugs.html">Found a bug</a>?
<br />
Created using <a href="https://www.sphinx-doc.org/">Sphinx</a> 2.4.4.
</div>
</body>
</html>