<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>C-Extension on Tarragon</title><link>https://tarrragon.github.io/blog/tags/c-extension/</link><description>Recent content in C-Extension on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Mon, 02 Feb 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/c-extension/index.xml" rel="self" type="application/rss+xml"/><item><title>案例：Cython 加速 Markdown 解析</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/cython-markdown/</link><pubDate>Wed, 21 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/cython-markdown/</guid><description>&lt;p>本案例基於 &lt;code>.claude/lib/markdown_link_checker.py&lt;/code> 的實際程式碼，展示如何用 Cython 加速文字解析。&lt;/p>
&lt;h2 id="先備知識">先備知識&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/cython/" data-link-title="4.2 Cython：Python 語法的 C 速度" data-link-desc="使用 Cython 加速 Python 程式碼">4.2 Cython：Python 語法的 C 速度&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="問題背景">問題背景&lt;/h2>
&lt;h3 id="現有設計">現有設計&lt;/h3>
&lt;p>&lt;code>markdown_link_checker.py&lt;/code> 使用純 Python 解析 Markdown 連結。讓我們看看核心程式碼：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">re&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Dict&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">MarkdownLinkChecker&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Markdown 連結檢查器&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="c1"># Markdown 連結正則表達式&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 匹配 [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target) 格式，排除圖片 ![alt](/python-advanced/05-c-extensions/case-studies/cython-markdown/src)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="n">INLINE_LINK_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="sa">r&lt;/span>&lt;span class="s1">&amp;#39;(?&amp;lt;!!)\[([^\]]+)\]\(([^)]+)\)&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 引用式連結定義 [ref]: target&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="n">REFERENCE_DEF_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="sa">r&lt;/span>&lt;span class="s1">&amp;#39;^\s*\[([^\]]+)\]:\s*(.+)$&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">MULTILINE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 引用式連結使用 [text][ref]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="n">REFERENCE_USE_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="sa">r&lt;/span>&lt;span class="s1">&amp;#39;\[([^\]]+)\]\[([^\]]+)\]&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="k">def&lt;/span> &lt;span class="nf">parse_markdown_links&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">Dict&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="s2"> 解析 Markdown 內容中的所有連結
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="s2"> Args:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="s2"> content: Markdown 內容
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">&lt;span class="s2"> list[dict]: 連結列表，每個包含 text, target, line
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="n">links&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="n">lines&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="s1">&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 首先收集引用式連結定義&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="n">reference_defs&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="k">match&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">REFERENCE_DEF_PATTERN&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">finditer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl"> &lt;span class="n">ref_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">lower&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="n">ref_target&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl"> &lt;span class="n">reference_defs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">ref_name&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ref_target&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">44&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 追蹤是否在程式碼區塊內&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">45&lt;/span>&lt;span class="cl"> &lt;span class="n">in_code_block&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">False&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">46&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">47&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 解析行內連結&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">48&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">line_num&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">line&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">enumerate&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">lines&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">49&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 檢查程式碼區塊開始/結束&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">50&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">line&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">startswith&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;```&amp;#34;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">51&lt;/span>&lt;span class="cl"> &lt;span class="n">in_code_block&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">in_code_block&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">52&lt;/span>&lt;span class="cl"> &lt;span class="k">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">53&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">54&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 跳過程式碼區塊內的連結&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">55&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">in_code_block&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">56&lt;/span>&lt;span class="cl"> &lt;span class="k">continue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">57&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">58&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 行內連結 [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">59&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="k">match&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">INLINE_LINK_PATTERN&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">finditer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">60&lt;/span>&lt;span class="cl"> &lt;span class="n">links&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">61&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">62&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;target&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">63&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;line&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">line_num&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">64&lt;/span>&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">65&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">66&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 引用式連結 [text][ref]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">67&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="k">match&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="bp">self&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">REFERENCE_USE_PATTERN&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">finditer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">line&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">68&lt;/span>&lt;span class="cl"> &lt;span class="n">ref_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">lower&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">69&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">ref_name&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">reference_defs&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">70&lt;/span>&lt;span class="cl"> &lt;span class="n">links&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">({&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">71&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;text&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="k">match&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">group&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">72&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;target&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">reference_defs&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">ref_name&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">73&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;line&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">line_num&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">74&lt;/span>&lt;span class="cl"> &lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">75&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">76&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">links&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="效能限制">效能限制&lt;/h3>
&lt;p>純 Python 的限制：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>正則表達式呼叫開銷&lt;/strong>：每次 &lt;code>finditer()&lt;/code> 都有 Python 層級的迭代器開銷&lt;/li>
&lt;li>&lt;strong>迴圈效率不如 C&lt;/strong>：Python 的 for 迴圈涉及迭代器協議和物件建立&lt;/li>
&lt;li>&lt;strong>字串處理有額外開銷&lt;/strong>：&lt;code>split()&lt;/code>、&lt;code>strip()&lt;/code>、&lt;code>startswith()&lt;/code> 都會建立新物件&lt;/li>
&lt;li>&lt;strong>字典存取開銷&lt;/strong>：&lt;code>reference_defs[ref_name]&lt;/code> 涉及雜湊計算和物件比較&lt;/li>
&lt;/ul>
&lt;p>當處理大量 Markdown 文件（例如整個文件專案）時，這些開銷會累積成可觀的效能損失。&lt;/p>
&lt;h2 id="進階解決方案">進階解決方案&lt;/h2>
&lt;h3 id="優化目標">優化目標&lt;/h3>
&lt;ol>
&lt;li>&lt;strong>保持相同的 API&lt;/strong>：不改變 &lt;code>parse_markdown_links()&lt;/code> 的輸入輸出格式&lt;/li>
&lt;li>&lt;strong>顯著提升解析速度&lt;/strong>：目標 2-5x 加速&lt;/li>
&lt;li>&lt;strong>容易整合到現有專案&lt;/strong>：編譯後可直接替換原模組&lt;/li>
&lt;/ol>
&lt;h3 id="實作步驟">實作步驟&lt;/h3>
&lt;h4 id="步驟-1建立-pyx-檔案">步驟 1：建立 .pyx 檔案&lt;/h4>
&lt;p>首先，建立基本的 Cython 檔案結構：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cython" data-lang="cython">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c"># markdown_parser.pyx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="sd">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="sd">Cython accelerated Markdown link parser.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="sd">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="sd">This module provides fast parsing of Markdown links,
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="sd">compatible with the original Python implementation.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="sd">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="k">import&lt;/span> &lt;span class="nn">re&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="k">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="k">import&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Dict&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="c"># Compile regex patterns at module level for reuse&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="k">cdef&lt;/span> &lt;span class="kt">object&lt;/span> &lt;span class="nf">INLINE_LINK_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="s">r&amp;#39;(?&amp;lt;!!)\[([^\]]+)\]\(([^)]+)\)&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="k">cdef&lt;/span> &lt;span class="kt">object&lt;/span> &lt;span class="nf">REFERENCE_DEF_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="s">r&amp;#39;^\s*\[([^\]]+)\]:\s*(.+)$&amp;#39;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">MULTILINE&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="k">cdef&lt;/span> &lt;span class="kt">object&lt;/span> &lt;span class="nf">REFERENCE_USE_PATTERN&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">re&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">compile&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="s">r&amp;#39;\[([^\]]+)\]\[([^\]]+)\]&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>重點說明&lt;/strong>：&lt;/p></description><content:encoded><![CDATA[<p>本案例基於 <code>.claude/lib/markdown_link_checker.py</code> 的實際程式碼，展示如何用 Cython 加速文字解析。</p>
<h2 id="先備知識">先備知識</h2>
<ul>
<li><a href="/blog/python-advanced/05-c-extensions/cython/" data-link-title="4.2 Cython：Python 語法的 C 速度" data-link-desc="使用 Cython 加速 Python 程式碼">4.2 Cython：Python 語法的 C 速度</a></li>
<li><a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python</a></li>
</ul>
<h2 id="問題背景">問題背景</h2>
<h3 id="現有設計">現有設計</h3>
<p><code>markdown_link_checker.py</code> 使用純 Python 解析 Markdown 連結。讓我們看看核心程式碼：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">re</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Dict</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">class</span> <span class="nc">MarkdownLinkChecker</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Markdown 連結檢查器&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="c1"># Markdown 連結正則表達式</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="c1"># 匹配 [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target) 格式，排除圖片 ![alt](/python-advanced/05-c-extensions/case-studies/cython-markdown/src)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">INLINE_LINK_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="sa">r</span><span class="s1">&#39;(?&lt;!!)\[([^\]]+)\]\(([^)]+)\)&#39;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="c1"># 引用式連結定義 [ref]: target</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="n">REFERENCE_DEF_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="sa">r</span><span class="s1">&#39;^\s*\[([^\]]+)\]:\s*(.+)$&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="n">re</span><span class="o">.</span><span class="n">MULTILINE</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="c1"># 引用式連結使用 [text][ref]</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">REFERENCE_USE_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="sa">r</span><span class="s1">&#39;\[([^\]]+)\]\[([^\]]+)\]&#39;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="k">def</span> <span class="nf">parse_markdown_links</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Dict</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="s2">        解析 Markdown 內容中的所有連結
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="s2">        Args:
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="s2">            content: Markdown 內容
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="s2">        Returns:
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="s2">            list[dict]: 連結列表，每個包含 text, target, line
</span></span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="s2">        &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">        <span class="n">links</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">        <span class="n">lines</span> <span class="o">=</span> <span class="n">content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="c1"># 首先收集引用式連結定義</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">        <span class="n">reference_defs</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">        <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">REFERENCE_DEF_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">            <span class="n">ref_name</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">            <span class="n">ref_target</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">            <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">
</span></span><span class="line"><span class="ln">44</span><span class="cl">        <span class="c1"># 追蹤是否在程式碼區塊內</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">        <span class="n">in_code_block</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">
</span></span><span class="line"><span class="ln">47</span><span class="cl">        <span class="c1"># 解析行內連結</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">        <span class="k">for</span> <span class="n">line_num</span><span class="p">,</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">start</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">            <span class="c1"># 檢查程式碼區塊開始/結束</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl">            <span class="k">if</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&#34;```&#34;</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">                <span class="n">in_code_block</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">in_code_block</span>
</span></span><span class="line"><span class="ln">52</span><span class="cl">                <span class="k">continue</span>
</span></span><span class="line"><span class="ln">53</span><span class="cl">
</span></span><span class="line"><span class="ln">54</span><span class="cl">            <span class="c1"># 跳過程式碼區塊內的連結</span>
</span></span><span class="line"><span class="ln">55</span><span class="cl">            <span class="k">if</span> <span class="n">in_code_block</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl">                <span class="k">continue</span>
</span></span><span class="line"><span class="ln">57</span><span class="cl">
</span></span><span class="line"><span class="ln">58</span><span class="cl">            <span class="c1"># 行內連結 [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target)</span>
</span></span><span class="line"><span class="ln">59</span><span class="cl">            <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">INLINE_LINK_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">60</span><span class="cl">                <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">61</span><span class="cl">                    <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">62</span><span class="cl">                    <span class="s2">&#34;target&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">63</span><span class="cl">                    <span class="s2">&#34;line&#34;</span><span class="p">:</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln">64</span><span class="cl">                <span class="p">})</span>
</span></span><span class="line"><span class="ln">65</span><span class="cl">
</span></span><span class="line"><span class="ln">66</span><span class="cl">            <span class="c1"># 引用式連結 [text][ref]</span>
</span></span><span class="line"><span class="ln">67</span><span class="cl">            <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">REFERENCE_USE_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">68</span><span class="cl">                <span class="n">ref_name</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">69</span><span class="cl">                <span class="k">if</span> <span class="n">ref_name</span> <span class="ow">in</span> <span class="n">reference_defs</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">70</span><span class="cl">                    <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="ln">71</span><span class="cl">                        <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">72</span><span class="cl">                        <span class="s2">&#34;target&#34;</span><span class="p">:</span> <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">73</span><span class="cl">                        <span class="s2">&#34;line&#34;</span><span class="p">:</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln">74</span><span class="cl">                    <span class="p">})</span>
</span></span><span class="line"><span class="ln">75</span><span class="cl">
</span></span><span class="line"><span class="ln">76</span><span class="cl">        <span class="k">return</span> <span class="n">links</span></span></span></code></pre></div><h3 id="效能限制">效能限制</h3>
<p>純 Python 的限制：</p>
<ul>
<li><strong>正則表達式呼叫開銷</strong>：每次 <code>finditer()</code> 都有 Python 層級的迭代器開銷</li>
<li><strong>迴圈效率不如 C</strong>：Python 的 for 迴圈涉及迭代器協議和物件建立</li>
<li><strong>字串處理有額外開銷</strong>：<code>split()</code>、<code>strip()</code>、<code>startswith()</code> 都會建立新物件</li>
<li><strong>字典存取開銷</strong>：<code>reference_defs[ref_name]</code> 涉及雜湊計算和物件比較</li>
</ul>
<p>當處理大量 Markdown 文件（例如整個文件專案）時，這些開銷會累積成可觀的效能損失。</p>
<h2 id="進階解決方案">進階解決方案</h2>
<h3 id="優化目標">優化目標</h3>
<ol>
<li><strong>保持相同的 API</strong>：不改變 <code>parse_markdown_links()</code> 的輸入輸出格式</li>
<li><strong>顯著提升解析速度</strong>：目標 2-5x 加速</li>
<li><strong>容易整合到現有專案</strong>：編譯後可直接替換原模組</li>
</ol>
<h3 id="實作步驟">實作步驟</h3>
<h4 id="步驟-1建立-pyx-檔案">步驟 1：建立 .pyx 檔案</h4>
<p>首先，建立基本的 Cython 檔案結構：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># markdown_parser.pyx</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="sd">Cython accelerated Markdown link parser.
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="sd">This module provides fast parsing of Markdown links,
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="sd">compatible with the original Python implementation.
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="sd">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="k">import</span> <span class="nn">re</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="k">from</span> <span class="nn">typing</span> <span class="k">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Dict</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c"># Compile regex patterns at module level for reuse</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">INLINE_LINK_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="s">r&#39;(?&lt;!!)\[([^\]]+)\]\(([^)]+)\)&#39;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">REFERENCE_DEF_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="s">r&#39;^\s*\[([^\]]+)\]:\s*(.+)$&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="n">re</span><span class="o">.</span><span class="n">MULTILINE</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">REFERENCE_USE_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="s">r&#39;\[([^\]]+)\]\[([^\]]+)\]&#39;</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><p><strong>重點說明</strong>：</p>
<ul>
<li>使用 <code>cdef object</code> 宣告正則表達式物件，讓 Cython 知道這些是 Python 物件</li>
<li>將正則表達式編譯放在模組層級，避免重複編譯</li>
<li>保留 docstring 和 type hints 以維護可讀性</li>
</ul>
<h4 id="步驟-2添加型別宣告">步驟 2：添加型別宣告</h4>
<p>為關鍵變數添加 C 型別宣告：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># markdown_parser.pyx (continued)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">cdef</span> <span class="k">class</span> <span class="nf">LinkInfo</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="sd">    C-level struct to hold link information.
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="sd">    Faster than Python dict for internal operations.
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">str</span> <span class="nf">text</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">str</span> <span class="nf">target</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">int</span> <span class="nf">line</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">str</span> <span class="n">text</span><span class="p">,</span> <span class="nb">str</span> <span class="n">target</span><span class="p">,</span> <span class="nb">int</span> <span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">text</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="o">=</span> <span class="n">target</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">line</span> <span class="o">=</span> <span class="n">line</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">def</span> <span class="nf">to_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="sd">&#34;&#34;&#34;Convert to dictionary for API compatibility.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">            <span class="s">&#34;text&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">text</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">            <span class="s">&#34;target&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">target</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">            <span class="s">&#34;line&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">line</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="k">cdef</span> <span class="kt">bint</span> <span class="nf">is_code_fence</span><span class="p">(</span><span class="nb">str</span> <span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="sd">    Check if line is a code fence marker.
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="sd">    cdef function: only callable from Cython, fastest.
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="k">cdef</span> <span class="kt">str</span> <span class="nf">stripped</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="k">return</span> <span class="n">stripped</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#34;```&#34;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">stripped</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#34;~~~&#34;</span><span class="p">)</span></span></span></code></pre></div><p><strong>重點說明</strong>：</p>
<ul>
<li><code>cdef class LinkInfo</code>：使用 Cython 的擴展類別，內部存取比 Python dict 快</li>
<li><code>cdef public</code>：讓屬性可以從 Python 存取，同時保持 C 層級效率</li>
<li><code>cdef bint</code>：使用 C 的布林型別（0 或 1），比 Python 的 <code>bool</code> 快</li>
<li><code>cdef</code> 函式：只能從 Cython 呼叫，沒有 Python 呼叫開銷</li>
</ul>
<h4 id="步驟-3優化迴圈">步驟 3：優化迴圈</h4>
<p>使用 Cython 優化主要的解析迴圈：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># markdown_parser.pyx (continued)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">cdef</span> <span class="kt">list</span> <span class="nf">_parse_inline_links</span><span class="p">(</span><span class="nb">list</span> <span class="n">lines</span><span class="p">,</span> <span class="nb">dict</span> <span class="n">reference_defs</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="sd">    Parse inline and reference links from lines.
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="sd">    Internal function with optimized loop.
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="nb">list</span> <span class="n">links</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="nb">int</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="nb">int</span> <span class="n">total_lines</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="n">bint</span> <span class="n">in_code_block</span> <span class="o">=</span> <span class="bp">False</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="nb">str</span> <span class="n">line</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_name</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="nb">object</span> <span class="n">match</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">for</span> <span class="n">line_num</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">total_lines</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="n">line</span> <span class="o">=</span> <span class="n">lines</span><span class="p">[</span><span class="n">line_num</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="c"># Check code fence</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="k">if</span> <span class="n">is_code_fence</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">            <span class="n">in_code_block</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">in_code_block</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="k">if</span> <span class="n">in_code_block</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="c"># Parse inline links [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">INLINE_LINK_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">            <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">LinkInfo</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">                <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">                <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">                <span class="n">line_num</span> <span class="o">+</span> <span class="mf">1</span>  <span class="c"># 1-indexed</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">            <span class="p">))</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="c"># Parse reference links [text][ref]</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">REFERENCE_USE_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">            <span class="n">ref_name</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">            <span class="k">if</span> <span class="n">ref_name</span> <span class="ow">in</span> <span class="n">reference_defs</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">                <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">LinkInfo</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">                    <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">                    <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">                    <span class="n">line_num</span> <span class="o">+</span> <span class="mf">1</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">                <span class="p">))</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">
</span></span><span class="line"><span class="ln">47</span><span class="cl">    <span class="k">return</span> <span class="n">links</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">
</span></span><span class="line"><span class="ln">49</span><span class="cl"><span class="k">cdef</span> <span class="kt">dict</span> <span class="nf">_collect_reference_defs</span><span class="p">(</span><span class="nb">str</span> <span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">51</span><span class="cl"><span class="sd">    Collect reference link definitions from content.
</span></span></span><span class="line"><span class="ln">52</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">53</span><span class="cl"><span class="sd">    Returns dict mapping ref_name -&gt; target.
</span></span></span><span class="line"><span class="ln">54</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">55</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl">        <span class="nb">dict</span> <span class="n">reference_defs</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln">57</span><span class="cl">        <span class="nb">object</span> <span class="n">match</span>
</span></span><span class="line"><span class="ln">58</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_name</span>
</span></span><span class="line"><span class="ln">59</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln">60</span><span class="cl">
</span></span><span class="line"><span class="ln">61</span><span class="cl">    <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">REFERENCE_DEF_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">62</span><span class="cl">        <span class="n">ref_name</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">63</span><span class="cl">        <span class="n">ref_target</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">64</span><span class="cl">        <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln">65</span><span class="cl">
</span></span><span class="line"><span class="ln">66</span><span class="cl">    <span class="k">return</span> <span class="n">reference_defs</span></span></span></code></pre></div><p><strong>重點說明</strong>：</p>
<ul>
<li><code>cdef list</code>、<code>cdef dict</code>：明確宣告容器型別，減少型別檢查開銷</li>
<li><code>cdef int line_num</code>：使用 C 整數進行迴圈計數</li>
<li><code>cdef bint in_code_block</code>：使用 C 布林型別追蹤狀態</li>
<li>將功能分解成多個 <code>cdef</code> 函式，每個函式專注單一職責</li>
</ul>
<h4 id="步驟-4建立公開-api">步驟 4：建立公開 API</h4>
<p>使用 <code>cpdef</code> 或 <code>def</code> 建立可從 Python 呼叫的公開介面：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># markdown_parser.pyx (continued)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">cpdef</span> <span class="kt">list</span> <span class="nf">parse_markdown_links</span><span class="p">(</span><span class="nb">str</span> <span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="sd">    Parse all links from Markdown content.
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="sd">    This is the main public API, compatible with the original
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="sd">    Python implementation.
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="sd">    Args:
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="sd">        content: Markdown content string
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="sd">    Returns:
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="sd">        List of dicts with &#39;text&#39;, &#39;target&#39;, &#39;line&#39; keys
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="nb">list</span> <span class="n">lines</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="nb">dict</span> <span class="n">reference_defs</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="nb">list</span> <span class="n">link_infos</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="nb">list</span> <span class="n">result</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="n">LinkInfo</span> <span class="n">info</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="c"># Split content into lines</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="n">lines</span> <span class="o">=</span> <span class="n">content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="c"># Collect reference definitions</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">reference_defs</span> <span class="o">=</span> <span class="n">_collect_reference_defs</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="c"># Parse all links</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="n">link_infos</span> <span class="o">=</span> <span class="n">_parse_inline_links</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">reference_defs</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="c"># Convert to dict format for API compatibility</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="p">[</span><span class="n">info</span><span class="o">.</span><span class="n">to_dict</span><span class="p">()</span> <span class="k">for</span> <span class="n">info</span> <span class="ow">in</span> <span class="n">link_infos</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="k">return</span> <span class="n">result</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="k">def</span> <span class="nf">parse_markdown_links_py</span><span class="p">(</span><span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Dict</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="sd">    Python-compatible wrapper with type hints.
</span></span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="sd">    Identical to parse_markdown_links but with explicit
</span></span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="sd">    Python type annotations for better IDE support.
</span></span></span><span class="line"><span class="ln">43</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">    <span class="k">return</span> <span class="n">parse_markdown_links</span><span class="p">(</span><span class="n">content</span><span class="p">)</span></span></span></code></pre></div><p><strong>重點說明</strong>：</p>
<ul>
<li><code>cpdef</code>：同時產生 Python 和 C 版本，從 Python 呼叫時用 Python 版本，從 Cython 呼叫時用 C 版本</li>
<li>保持 API 相容性：回傳格式與原始 Python 版本完全相同</li>
<li>提供 <code>_py</code> 版本：帶有完整型別提示，改善 IDE 支援</li>
</ul>
<h4 id="步驟-5建立-setuppy">步驟 5：建立 setup.py</h4>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># setup.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="s2">Build script for Cython markdown parser.
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s2">Usage:
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    python setup.py build_ext --inplace
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">Or for development with automatic rebuild:
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">    pip install -e .
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="kn">from</span> <span class="nn">setuptools</span> <span class="kn">import</span> <span class="n">setup</span><span class="p">,</span> <span class="n">Extension</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="kn">from</span> <span class="nn">Cython.Build</span> <span class="kn">import</span> <span class="n">cythonize</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">extensions</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="n">Extension</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="s2">&#34;markdown_parser&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="n">sources</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;markdown_parser.pyx&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="c1"># Optional: add compiler directives for optimization</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="c1"># extra_compile_args=[&#34;-O3&#34;],</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="n">setup</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="n">name</span><span class="o">=</span><span class="s2">&#34;markdown_parser&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">version</span><span class="o">=</span><span class="s2">&#34;0.1.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">description</span><span class="o">=</span><span class="s2">&#34;Cython accelerated Markdown link parser&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="n">ext_modules</span><span class="o">=</span><span class="n">cythonize</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="n">extensions</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="n">compiler_directives</span><span class="o">=</span><span class="p">{</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">            <span class="s2">&#34;language_level&#34;</span><span class="p">:</span> <span class="s2">&#34;3&#34;</span><span class="p">,</span>      <span class="c1"># Python 3 syntax</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">            <span class="s2">&#34;boundscheck&#34;</span><span class="p">:</span> <span class="kc">False</span><span class="p">,</span>       <span class="c1"># Disable bounds checking</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">            <span class="s2">&#34;wraparound&#34;</span><span class="p">:</span> <span class="kc">False</span><span class="p">,</span>        <span class="c1"># Disable negative indexing</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">            <span class="s2">&#34;cdivision&#34;</span><span class="p">:</span> <span class="kc">True</span><span class="p">,</span>          <span class="c1"># Use C division semantics</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">        <span class="p">},</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">        <span class="n">annotate</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>  <span class="c1"># Generate HTML annotation file</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="p">),</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="n">zip_safe</span><span class="o">=</span><span class="kc">False</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><p><strong>編譯指令說明</strong>：</p>
<table>
  <thead>
      <tr>
          <th>指令</th>
          <th>說明</th>
          <th>效能影響</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><code>language_level=3</code></td>
          <td>使用 Python 3 語法</td>
          <td>無</td>
      </tr>
      <tr>
          <td><code>boundscheck=False</code></td>
          <td>停用陣列邊界檢查</td>
          <td>加速 5-10%</td>
      </tr>
      <tr>
          <td><code>wraparound=False</code></td>
          <td>停用負數索引支援</td>
          <td>加速 2-5%</td>
      </tr>
      <tr>
          <td><code>cdivision=True</code></td>
          <td>使用 C 的除法（不檢查除以零）</td>
          <td>加速除法運算</td>
      </tr>
      <tr>
          <td><code>annotate=True</code></td>
          <td>產生 HTML 註解報告</td>
          <td>僅開發時使用</td>
      </tr>
  </tbody>
</table>
<h3 id="完整程式碼">完整程式碼</h3>
<p>將以上所有部分整合成完整的 <code>.pyx</code> 檔案：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c"># markdown_parser.pyx</span>
</span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="sd">Cython accelerated Markdown link parser.
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">  5</span><span class="cl"><span class="sd">This module provides fast parsing of Markdown links,
</span></span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="sd">compatible with the original Python implementation.
</span></span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="sd">Build:
</span></span></span><span class="line"><span class="ln">  9</span><span class="cl"><span class="sd">    python setup.py build_ext --inplace
</span></span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln"> 11</span><span class="cl"><span class="sd">Usage:
</span></span></span><span class="line"><span class="ln"> 12</span><span class="cl"><span class="sd">    from markdown_parser import parse_markdown_links
</span></span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="sd">    links = parse_markdown_links(markdown_content)
</span></span></span><span class="line"><span class="ln"> 14</span><span class="cl"><span class="sd">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 15</span><span class="cl">
</span></span><span class="line"><span class="ln"> 16</span><span class="cl"><span class="k">import</span> <span class="nn">re</span>
</span></span><span class="line"><span class="ln"> 17</span><span class="cl"><span class="k">from</span> <span class="nn">typing</span> <span class="k">import</span> <span class="n">List</span><span class="p">,</span> <span class="n">Dict</span>
</span></span><span class="line"><span class="ln"> 18</span><span class="cl">
</span></span><span class="line"><span class="ln"> 19</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 20</span><span class="cl"><span class="c"># Compiled regex patterns (module level for reuse)</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 22</span><span class="cl">
</span></span><span class="line"><span class="ln"> 23</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">INLINE_LINK_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 24</span><span class="cl">    <span class="s">r&#39;(?&lt;!!)\[([^\]]+)\]\(([^)]+)\)&#39;</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 26</span><span class="cl">
</span></span><span class="line"><span class="ln"> 27</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">REFERENCE_DEF_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 28</span><span class="cl">    <span class="s">r&#39;^\s*\[([^\]]+)\]:\s*(.+)$&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 29</span><span class="cl">    <span class="n">re</span><span class="o">.</span><span class="n">MULTILINE</span>
</span></span><span class="line"><span class="ln"> 30</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 31</span><span class="cl">
</span></span><span class="line"><span class="ln"> 32</span><span class="cl"><span class="k">cdef</span> <span class="kt">object</span> <span class="nf">REFERENCE_USE_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 33</span><span class="cl">    <span class="s">r&#39;\[([^\]]+)\]\[([^\]]+)\]&#39;</span>
</span></span><span class="line"><span class="ln"> 34</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 35</span><span class="cl">
</span></span><span class="line"><span class="ln"> 36</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 37</span><span class="cl"><span class="c"># C-level data structures</span>
</span></span><span class="line"><span class="ln"> 38</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 39</span><span class="cl">
</span></span><span class="line"><span class="ln"> 40</span><span class="cl"><span class="k">cdef</span> <span class="k">class</span> <span class="nf">LinkInfo</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 42</span><span class="cl"><span class="sd">    C-level struct to hold link information.
</span></span></span><span class="line"><span class="ln"> 43</span><span class="cl"><span class="sd">    Faster than Python dict for internal operations.
</span></span></span><span class="line"><span class="ln"> 44</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">str</span> <span class="nf">text</span>
</span></span><span class="line"><span class="ln"> 46</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">str</span> <span class="nf">target</span>
</span></span><span class="line"><span class="ln"> 47</span><span class="cl">    <span class="k">cdef</span> <span class="kr">public</span> <span class="kt">int</span> <span class="nf">line</span>
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">
</span></span><span class="line"><span class="ln"> 49</span><span class="cl">    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">str</span> <span class="n">text</span><span class="p">,</span> <span class="nb">str</span> <span class="n">target</span><span class="p">,</span> <span class="nb">int</span> <span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 50</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">text</span> <span class="o">=</span> <span class="n">text</span>
</span></span><span class="line"><span class="ln"> 51</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">target</span> <span class="o">=</span> <span class="n">target</span>
</span></span><span class="line"><span class="ln"> 52</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">line</span> <span class="o">=</span> <span class="n">line</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl">
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">    <span class="k">def</span> <span class="nf">to_dict</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 55</span><span class="cl">        <span class="sd">&#34;&#34;&#34;Convert to dictionary for API compatibility.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 56</span><span class="cl">        <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 57</span><span class="cl">            <span class="s">&#34;text&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">text</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 58</span><span class="cl">            <span class="s">&#34;target&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">target</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 59</span><span class="cl">            <span class="s">&#34;line&#34;</span><span class="p">:</span> <span class="bp">self</span><span class="o">.</span><span class="n">line</span>
</span></span><span class="line"><span class="ln"> 60</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">
</span></span><span class="line"><span class="ln"> 62</span><span class="cl">    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">        <span class="k">return</span> <span class="n">f</span><span class="s">&#34;LinkInfo(text={self.text!r}, target={self.target!r}, line={self.line})&#34;</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">
</span></span><span class="line"><span class="ln"> 65</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl"><span class="c"># Internal helper functions (cdef = C-only, fastest)</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl">
</span></span><span class="line"><span class="ln"> 69</span><span class="cl"><span class="k">cdef</span> <span class="kt">bint</span> <span class="nf">is_code_fence</span><span class="p">(</span><span class="nb">str</span> <span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 71</span><span class="cl"><span class="sd">    Check if line is a code fence marker.
</span></span></span><span class="line"><span class="ln"> 72</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">    <span class="k">cdef</span> <span class="kt">str</span> <span class="nf">stripped</span> <span class="o">=</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl">    <span class="k">return</span> <span class="n">stripped</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#34;```&#34;</span><span class="p">)</span> <span class="ow">or</span> <span class="n">stripped</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">&#34;~~~&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">
</span></span><span class="line"><span class="ln"> 76</span><span class="cl"><span class="k">cdef</span> <span class="kt">dict</span> <span class="nf">_collect_reference_defs</span><span class="p">(</span><span class="nb">str</span> <span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 78</span><span class="cl"><span class="sd">    Collect reference link definitions from content.
</span></span></span><span class="line"><span class="ln"> 79</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 81</span><span class="cl">        <span class="nb">dict</span> <span class="n">reference_defs</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 82</span><span class="cl">        <span class="nb">object</span> <span class="n">match</span>
</span></span><span class="line"><span class="ln"> 83</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_name</span>
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">    <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">REFERENCE_DEF_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">        <span class="n">ref_name</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl">        <span class="n">ref_target</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">        <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">
</span></span><span class="line"><span class="ln"> 91</span><span class="cl">    <span class="k">return</span> <span class="n">reference_defs</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl">
</span></span><span class="line"><span class="ln"> 93</span><span class="cl"><span class="k">cdef</span> <span class="kt">list</span> <span class="nf">_parse_inline_links</span><span class="p">(</span><span class="nb">list</span> <span class="n">lines</span><span class="p">,</span> <span class="nb">dict</span> <span class="n">reference_defs</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="sd">    Parse inline and reference links from lines.
</span></span></span><span class="line"><span class="ln"> 96</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 97</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 98</span><span class="cl">        <span class="nb">list</span> <span class="n">links</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">        <span class="nb">int</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln">100</span><span class="cl">        <span class="nb">int</span> <span class="n">total_lines</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl">        <span class="n">bint</span> <span class="n">in_code_block</span> <span class="o">=</span> <span class="bp">False</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">        <span class="nb">str</span> <span class="n">line</span>
</span></span><span class="line"><span class="ln">103</span><span class="cl">        <span class="nb">str</span> <span class="n">ref_name</span>
</span></span><span class="line"><span class="ln">104</span><span class="cl">        <span class="nb">object</span> <span class="n">match</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">
</span></span><span class="line"><span class="ln">106</span><span class="cl">    <span class="k">for</span> <span class="n">line_num</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">total_lines</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">107</span><span class="cl">        <span class="n">line</span> <span class="o">=</span> <span class="n">lines</span><span class="p">[</span><span class="n">line_num</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">108</span><span class="cl">
</span></span><span class="line"><span class="ln">109</span><span class="cl">        <span class="c"># Check code fence</span>
</span></span><span class="line"><span class="ln">110</span><span class="cl">        <span class="k">if</span> <span class="n">is_code_fence</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">111</span><span class="cl">            <span class="n">in_code_block</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">in_code_block</span>
</span></span><span class="line"><span class="ln">112</span><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="ln">113</span><span class="cl">
</span></span><span class="line"><span class="ln">114</span><span class="cl">        <span class="k">if</span> <span class="n">in_code_block</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">115</span><span class="cl">            <span class="k">continue</span>
</span></span><span class="line"><span class="ln">116</span><span class="cl">
</span></span><span class="line"><span class="ln">117</span><span class="cl">        <span class="c"># Parse inline links [text](/python-advanced/05-c-extensions/case-studies/cython-markdown/target)</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">INLINE_LINK_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">119</span><span class="cl">            <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">LinkInfo</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">120</span><span class="cl">                <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">121</span><span class="cl">                <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">122</span><span class="cl">                <span class="n">line_num</span> <span class="o">+</span> <span class="mf">1</span>
</span></span><span class="line"><span class="ln">123</span><span class="cl">            <span class="p">))</span>
</span></span><span class="line"><span class="ln">124</span><span class="cl">
</span></span><span class="line"><span class="ln">125</span><span class="cl">        <span class="c"># Parse reference links [text][ref]</span>
</span></span><span class="line"><span class="ln">126</span><span class="cl">        <span class="k">for</span> <span class="n">match</span> <span class="ow">in</span> <span class="n">REFERENCE_USE_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">127</span><span class="cl">            <span class="n">ref_name</span> <span class="o">=</span> <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">2</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">128</span><span class="cl">            <span class="k">if</span> <span class="n">ref_name</span> <span class="ow">in</span> <span class="n">reference_defs</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">129</span><span class="cl">                <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">LinkInfo</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">130</span><span class="cl">                    <span class="n">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mf">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">131</span><span class="cl">                    <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">132</span><span class="cl">                    <span class="n">line_num</span> <span class="o">+</span> <span class="mf">1</span>
</span></span><span class="line"><span class="ln">133</span><span class="cl">                <span class="p">))</span>
</span></span><span class="line"><span class="ln">134</span><span class="cl">
</span></span><span class="line"><span class="ln">135</span><span class="cl">    <span class="k">return</span> <span class="n">links</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">
</span></span><span class="line"><span class="ln">137</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln">138</span><span class="cl"><span class="c"># Public API (cpdef = callable from both Python and Cython)</span>
</span></span><span class="line"><span class="ln">139</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln">140</span><span class="cl">
</span></span><span class="line"><span class="ln">141</span><span class="cl"><span class="k">cpdef</span> <span class="kt">list</span> <span class="nf">parse_markdown_links</span><span class="p">(</span><span class="nb">str</span> <span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">142</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">143</span><span class="cl"><span class="sd">    Parse all links from Markdown content.
</span></span></span><span class="line"><span class="ln">144</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">145</span><span class="cl"><span class="sd">    Args:
</span></span></span><span class="line"><span class="ln">146</span><span class="cl"><span class="sd">        content: Markdown content string
</span></span></span><span class="line"><span class="ln">147</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">148</span><span class="cl"><span class="sd">    Returns:
</span></span></span><span class="line"><span class="ln">149</span><span class="cl"><span class="sd">        List of dicts with &#39;text&#39;, &#39;target&#39;, &#39;line&#39; keys
</span></span></span><span class="line"><span class="ln">150</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">151</span><span class="cl"><span class="sd">    Example:
</span></span></span><span class="line"><span class="ln">152</span><span class="cl"><span class="sd">        &gt;&gt;&gt; content = &#34;[Click here](https://example.com)&#34;
</span></span></span><span class="line"><span class="ln">153</span><span class="cl"><span class="sd">        &gt;&gt;&gt; links = parse_markdown_links(content)
</span></span></span><span class="line"><span class="ln">154</span><span class="cl"><span class="sd">        &gt;&gt;&gt; links[0][&#39;target&#39;]
</span></span></span><span class="line"><span class="ln">155</span><span class="cl"><span class="sd">        &#39;https://example.com&#39;
</span></span></span><span class="line"><span class="ln">156</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">157</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">158</span><span class="cl">        <span class="nb">list</span> <span class="n">lines</span>
</span></span><span class="line"><span class="ln">159</span><span class="cl">        <span class="nb">dict</span> <span class="n">reference_defs</span>
</span></span><span class="line"><span class="ln">160</span><span class="cl">        <span class="nb">list</span> <span class="n">link_infos</span>
</span></span><span class="line"><span class="ln">161</span><span class="cl">        <span class="nb">list</span> <span class="n">result</span>
</span></span><span class="line"><span class="ln">162</span><span class="cl">        <span class="n">LinkInfo</span> <span class="n">info</span>
</span></span><span class="line"><span class="ln">163</span><span class="cl">
</span></span><span class="line"><span class="ln">164</span><span class="cl">    <span class="n">lines</span> <span class="o">=</span> <span class="n">content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">165</span><span class="cl">    <span class="n">reference_defs</span> <span class="o">=</span> <span class="n">_collect_reference_defs</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">166</span><span class="cl">    <span class="n">link_infos</span> <span class="o">=</span> <span class="n">_parse_inline_links</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">reference_defs</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">167</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="p">[</span><span class="n">info</span><span class="o">.</span><span class="n">to_dict</span><span class="p">()</span> <span class="k">for</span> <span class="n">info</span> <span class="ow">in</span> <span class="n">link_infos</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">168</span><span class="cl">
</span></span><span class="line"><span class="ln">169</span><span class="cl">    <span class="k">return</span> <span class="n">result</span>
</span></span><span class="line"><span class="ln">170</span><span class="cl">
</span></span><span class="line"><span class="ln">171</span><span class="cl"><span class="c"># Python-compatible wrapper with full type hints</span>
</span></span><span class="line"><span class="ln">172</span><span class="cl"><span class="k">def</span> <span class="nf">parse_markdown_links_py</span><span class="p">(</span><span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">List</span><span class="p">[</span><span class="n">Dict</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">173</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">174</span><span class="cl"><span class="sd">    Python-compatible wrapper with type hints.
</span></span></span><span class="line"><span class="ln">175</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">176</span><span class="cl"><span class="sd">    Identical to parse_markdown_links but with explicit
</span></span></span><span class="line"><span class="ln">177</span><span class="cl"><span class="sd">    Python type annotations for better IDE support.
</span></span></span><span class="line"><span class="ln">178</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">179</span><span class="cl">    <span class="k">return</span> <span class="n">parse_markdown_links</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">180</span><span class="cl">
</span></span><span class="line"><span class="ln">181</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln">182</span><span class="cl"><span class="c"># Optional: Expose LinkInfo class for advanced usage</span>
</span></span><span class="line"><span class="ln">183</span><span class="cl"><span class="c"># ============================================================</span>
</span></span><span class="line"><span class="ln">184</span><span class="cl">
</span></span><span class="line"><span class="ln">185</span><span class="cl"><span class="k">def</span> <span class="nf">parse_markdown_links_fast</span><span class="p">(</span><span class="nb">str</span> <span class="n">content</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">186</span><span class="cl">    <span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">187</span><span class="cl"><span class="sd">    Parse links and return LinkInfo objects directly.
</span></span></span><span class="line"><span class="ln">188</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">189</span><span class="cl"><span class="sd">    Faster than parse_markdown_links() as it skips
</span></span></span><span class="line"><span class="ln">190</span><span class="cl"><span class="sd">    the dict conversion step.
</span></span></span><span class="line"><span class="ln">191</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln">192</span><span class="cl"><span class="sd">    Returns:
</span></span></span><span class="line"><span class="ln">193</span><span class="cl"><span class="sd">        List of LinkInfo objects
</span></span></span><span class="line"><span class="ln">194</span><span class="cl"><span class="sd">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">195</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">196</span><span class="cl">        <span class="nb">list</span> <span class="n">lines</span>
</span></span><span class="line"><span class="ln">197</span><span class="cl">        <span class="nb">dict</span> <span class="n">reference_defs</span>
</span></span><span class="line"><span class="ln">198</span><span class="cl">
</span></span><span class="line"><span class="ln">199</span><span class="cl">    <span class="n">lines</span> <span class="o">=</span> <span class="n">content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s">&#39;</span><span class="se">\n</span><span class="s">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">200</span><span class="cl">    <span class="n">reference_defs</span> <span class="o">=</span> <span class="n">_collect_reference_defs</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">201</span><span class="cl">    <span class="k">return</span> <span class="n">_parse_inline_links</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">reference_defs</span><span class="p">)</span></span></span></code></pre></div><h3 id="效能比較">效能比較</h3>
<p>建立效能測試腳本來比較純 Python 和 Cython 版本：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c1"># benchmark.py</span>
</span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="s2">Performance comparison between Python and Cython implementations.
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">  5</span><span class="cl"><span class="s2">Usage:
</span></span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="s2">    # First, build the Cython module
</span></span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="s2">    python setup.py build_ext --inplace
</span></span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">  9</span><span class="cl"><span class="s2">    # Then run benchmark
</span></span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="s2">    python benchmark.py
</span></span></span><span class="line"><span class="ln"> 11</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 12</span><span class="cl">
</span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="ln"> 14</span><span class="cl"><span class="kn">import</span> <span class="nn">statistics</span>
</span></span><span class="line"><span class="ln"> 15</span><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Callable</span><span class="p">,</span> <span class="n">List</span>
</span></span><span class="line"><span class="ln"> 16</span><span class="cl">
</span></span><span class="line"><span class="ln"> 17</span><span class="cl"><span class="c1"># Pure Python implementation (inline for comparison)</span>
</span></span><span class="line"><span class="ln"> 18</span><span class="cl"><span class="kn">import</span> <span class="nn">re</span>
</span></span><span class="line"><span class="ln"> 19</span><span class="cl">
</span></span><span class="line"><span class="ln"> 20</span><span class="cl"><span class="k">class</span> <span class="nc">PythonMarkdownParser</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Original pure Python implementation.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 22</span><span class="cl">
</span></span><span class="line"><span class="ln"> 23</span><span class="cl">    <span class="n">INLINE_LINK_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;(?&lt;!!)\[([^\]]+)\]\(([^)]+)\)&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 24</span><span class="cl">    <span class="n">REFERENCE_DEF_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;^\s*\[([^\]]+)\]:\s*(.+)$&#39;</span><span class="p">,</span> <span class="n">re</span><span class="o">.</span><span class="n">MULTILINE</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">    <span class="n">REFERENCE_USE_PATTERN</span> <span class="o">=</span> <span class="n">re</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="sa">r</span><span class="s1">&#39;\[([^\]]+)\]\[([^\]]+)\]&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 26</span><span class="cl">
</span></span><span class="line"><span class="ln"> 27</span><span class="cl">    <span class="k">def</span> <span class="nf">parse_markdown_links</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 28</span><span class="cl">        <span class="n">links</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 29</span><span class="cl">        <span class="n">lines</span> <span class="o">=</span> <span class="n">content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 30</span><span class="cl">
</span></span><span class="line"><span class="ln"> 31</span><span class="cl">        <span class="n">reference_defs</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 32</span><span class="cl">        <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">REFERENCE_DEF_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">content</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 33</span><span class="cl">            <span class="n">ref_name</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 34</span><span class="cl">            <span class="n">ref_target</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 35</span><span class="cl">            <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">ref_target</span>
</span></span><span class="line"><span class="ln"> 36</span><span class="cl">
</span></span><span class="line"><span class="ln"> 37</span><span class="cl">        <span class="n">in_code_block</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="ln"> 38</span><span class="cl">
</span></span><span class="line"><span class="ln"> 39</span><span class="cl">        <span class="k">for</span> <span class="n">line_num</span><span class="p">,</span> <span class="n">line</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">lines</span><span class="p">,</span> <span class="n">start</span><span class="o">=</span><span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 40</span><span class="cl">            <span class="k">if</span> <span class="n">line</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span><span class="o">.</span><span class="n">startswith</span><span class="p">(</span><span class="s2">&#34;```&#34;</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">                <span class="n">in_code_block</span> <span class="o">=</span> <span class="ow">not</span> <span class="n">in_code_block</span>
</span></span><span class="line"><span class="ln"> 42</span><span class="cl">                <span class="k">continue</span>
</span></span><span class="line"><span class="ln"> 43</span><span class="cl">
</span></span><span class="line"><span class="ln"> 44</span><span class="cl">            <span class="k">if</span> <span class="n">in_code_block</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">                <span class="k">continue</span>
</span></span><span class="line"><span class="ln"> 46</span><span class="cl">
</span></span><span class="line"><span class="ln"> 47</span><span class="cl">            <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">INLINE_LINK_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">                <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 49</span><span class="cl">                    <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 50</span><span class="cl">                    <span class="s2">&#34;target&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 51</span><span class="cl">                    <span class="s2">&#34;line&#34;</span><span class="p">:</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln"> 52</span><span class="cl">                <span class="p">})</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl">
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">            <span class="k">for</span> <span class="k">match</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">REFERENCE_USE_PATTERN</span><span class="o">.</span><span class="n">finditer</span><span class="p">(</span><span class="n">line</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 55</span><span class="cl">                <span class="n">ref_name</span> <span class="o">=</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 56</span><span class="cl">                <span class="k">if</span> <span class="n">ref_name</span> <span class="ow">in</span> <span class="n">reference_defs</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 57</span><span class="cl">                    <span class="n">links</span><span class="o">.</span><span class="n">append</span><span class="p">({</span>
</span></span><span class="line"><span class="ln"> 58</span><span class="cl">                        <span class="s2">&#34;text&#34;</span><span class="p">:</span> <span class="k">match</span><span class="o">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 59</span><span class="cl">                        <span class="s2">&#34;target&#34;</span><span class="p">:</span> <span class="n">reference_defs</span><span class="p">[</span><span class="n">ref_name</span><span class="p">],</span>
</span></span><span class="line"><span class="ln"> 60</span><span class="cl">                        <span class="s2">&#34;line&#34;</span><span class="p">:</span> <span class="n">line_num</span>
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">                    <span class="p">})</span>
</span></span><span class="line"><span class="ln"> 62</span><span class="cl">
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">        <span class="k">return</span> <span class="n">links</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">
</span></span><span class="line"><span class="ln"> 65</span><span class="cl"><span class="k">def</span> <span class="nf">generate_test_content</span><span class="p">(</span><span class="n">num_lines</span><span class="p">:</span> <span class="nb">int</span><span class="p">,</span> <span class="n">links_per_100_lines</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">10</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Generate test Markdown content with specified characteristics.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">    <span class="n">lines</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">num_lines</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 69</span><span class="cl">        <span class="k">if</span> <span class="n">i</span> <span class="o">%</span> <span class="p">(</span><span class="mi">100</span> <span class="o">//</span> <span class="n">links_per_100_lines</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">            <span class="c1"># Add an inline link</span>
</span></span><span class="line"><span class="ln"> 71</span><span class="cl">            <span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Check out [Link </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">](https://example.com/page</span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2">) for details.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 72</span><span class="cl">        <span class="k">elif</span> <span class="n">i</span> <span class="o">%</span> <span class="mi">50</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">            <span class="c1"># Add a code block</span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl">            <span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&#34;```python&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">            <span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;# This is code, links here [should](/python-advanced/05-c-extensions/case-studies/cython-markdown/be/ignored)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 76</span><span class="cl">            <span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="s2">&#34;```&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 78</span><span class="cl">            <span class="c1"># Regular text</span>
</span></span><span class="line"><span class="ln"> 79</span><span class="cl">            <span class="n">lines</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;This is line </span><span class="si">{</span><span class="n">i</span><span class="si">}</span><span class="s2"> with some regular text content.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">
</span></span><span class="line"><span class="ln"> 81</span><span class="cl">    <span class="k">return</span> <span class="s1">&#39;</span><span class="se">\n</span><span class="s1">&#39;</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">lines</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 82</span><span class="cl">
</span></span><span class="line"><span class="ln"> 83</span><span class="cl"><span class="k">def</span> <span class="nf">benchmark</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="n">Callable</span><span class="p">,</span> <span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">,</span> <span class="n">iterations</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">100</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Run benchmark and return statistics.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">    <span class="n">times</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">    <span class="c1"># Warmup</span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">        <span class="n">func</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">
</span></span><span class="line"><span class="ln"> 91</span><span class="cl">    <span class="c1"># Actual benchmark</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">iterations</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 93</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">        <span class="n">result</span> <span class="o">=</span> <span class="n">func</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 95</span><span class="cl">        <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 96</span><span class="cl">        <span class="n">times</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 97</span><span class="cl">
</span></span><span class="line"><span class="ln"> 98</span><span class="cl">    <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">        <span class="s2">&#34;mean&#34;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">,</span>  <span class="c1"># Convert to ms</span>
</span></span><span class="line"><span class="ln">100</span><span class="cl">        <span class="s2">&#34;stdev&#34;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">stdev</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl">        <span class="s2">&#34;min&#34;</span><span class="p">:</span> <span class="nb">min</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">        <span class="s2">&#34;max&#34;</span><span class="p">:</span> <span class="nb">max</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">103</span><span class="cl">        <span class="s2">&#34;links_found&#34;</span><span class="p">:</span> <span class="nb">len</span><span class="p">(</span><span class="n">result</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">104</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">
</span></span><span class="line"><span class="ln">106</span><span class="cl"><span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">107</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">60</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">108</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Markdown Link Parser Benchmark&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">109</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">60</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">110</span><span class="cl">
</span></span><span class="line"><span class="ln">111</span><span class="cl">    <span class="c1"># Test different content sizes</span>
</span></span><span class="line"><span class="ln">112</span><span class="cl">    <span class="n">sizes</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1000</span><span class="p">,</span> <span class="mi">5000</span><span class="p">,</span> <span class="mi">10000</span><span class="p">,</span> <span class="mi">50000</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">113</span><span class="cl">
</span></span><span class="line"><span class="ln">114</span><span class="cl">    <span class="n">python_parser</span> <span class="o">=</span> <span class="n">PythonMarkdownParser</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">115</span><span class="cl">
</span></span><span class="line"><span class="ln">116</span><span class="cl">    <span class="c1"># Try to import Cython version</span>
</span></span><span class="line"><span class="ln">117</span><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">        <span class="kn">from</span> <span class="nn">markdown_parser</span> <span class="kn">import</span> <span class="n">parse_markdown_links</span> <span class="k">as</span> <span class="n">cython_parse</span>
</span></span><span class="line"><span class="ln">119</span><span class="cl">        <span class="n">has_cython</span> <span class="o">=</span> <span class="kc">True</span>
</span></span><span class="line"><span class="ln">120</span><span class="cl">    <span class="k">except</span> <span class="ne">ImportError</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">121</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">Warning: Cython module not found.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">122</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;Run &#39;python setup.py build_ext --inplace&#39; first.</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">123</span><span class="cl">        <span class="n">has_cython</span> <span class="o">=</span> <span class="kc">False</span>
</span></span><span class="line"><span class="ln">124</span><span class="cl">
</span></span><span class="line"><span class="ln">125</span><span class="cl">    <span class="k">for</span> <span class="n">size</span> <span class="ow">in</span> <span class="n">sizes</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">126</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">--- Content size: </span><span class="si">{</span><span class="n">size</span><span class="si">}</span><span class="s2"> lines ---&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">127</span><span class="cl">        <span class="n">content</span> <span class="o">=</span> <span class="n">generate_test_content</span><span class="p">(</span><span class="n">size</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">128</span><span class="cl">
</span></span><span class="line"><span class="ln">129</span><span class="cl">        <span class="c1"># Python benchmark</span>
</span></span><span class="line"><span class="ln">130</span><span class="cl">        <span class="n">py_result</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">python_parser</span><span class="o">.</span><span class="n">parse_markdown_links</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">131</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Python:  </span><span class="si">{</span><span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2"> ms (+/- </span><span class="si">{</span><span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;stdev&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2"> ms)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">132</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;         Found </span><span class="si">{</span><span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;links_found&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2"> links&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">133</span><span class="cl">
</span></span><span class="line"><span class="ln">134</span><span class="cl">        <span class="c1"># Cython benchmark (if available)</span>
</span></span><span class="line"><span class="ln">135</span><span class="cl">        <span class="k">if</span> <span class="n">has_cython</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">            <span class="n">cy_result</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">cython_parse</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">137</span><span class="cl">            <span class="n">speedup</span> <span class="o">=</span> <span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span> <span class="o">/</span> <span class="n">cy_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">138</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Cython:  </span><span class="si">{</span><span class="n">cy_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2"> ms (+/- </span><span class="si">{</span><span class="n">cy_result</span><span class="p">[</span><span class="s1">&#39;stdev&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.3f</span><span class="si">}</span><span class="s2"> ms)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">139</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;         Speedup: </span><span class="si">{</span><span class="n">speedup</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2">x&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">140</span><span class="cl">
</span></span><span class="line"><span class="ln">141</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">&#34;</span> <span class="o">+</span> <span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">60</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">142</span><span class="cl">
</span></span><span class="line"><span class="ln">143</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">144</span><span class="cl">    <span class="n">main</span><span class="p">()</span></span></span></code></pre></div><h3 id="預期結果">預期結果</h3>
<p>執行效能測試後，預期會看到類似以下的結果：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">============================================================
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">Markdown Link Parser Benchmark
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">============================================================
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">--- Content size: 1000 lines ---
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">Python:  0.523 ms (+/- 0.031 ms)
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">         Found 100 links
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">Cython:  0.198 ms (+/- 0.012 ms)
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">         Speedup: 2.64x
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">--- Content size: 5000 lines ---
</span></span><span class="line"><span class="ln">12</span><span class="cl">Python:  2.617 ms (+/- 0.089 ms)
</span></span><span class="line"><span class="ln">13</span><span class="cl">         Found 500 links
</span></span><span class="line"><span class="ln">14</span><span class="cl">Cython:  0.892 ms (+/- 0.045 ms)
</span></span><span class="line"><span class="ln">15</span><span class="cl">         Speedup: 2.93x
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">--- Content size: 10000 lines ---
</span></span><span class="line"><span class="ln">18</span><span class="cl">Python:  5.234 ms (+/- 0.156 ms)
</span></span><span class="line"><span class="ln">19</span><span class="cl">         Found 1000 links
</span></span><span class="line"><span class="ln">20</span><span class="cl">Cython:  1.712 ms (+/- 0.078 ms)
</span></span><span class="line"><span class="ln">21</span><span class="cl">         Speedup: 3.06x
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl">--- Content size: 50000 lines ---
</span></span><span class="line"><span class="ln">24</span><span class="cl">Python:  26.18 ms (+/- 0.823 ms)
</span></span><span class="line"><span class="ln">25</span><span class="cl">         Found 5000 links
</span></span><span class="line"><span class="ln">26</span><span class="cl">Cython:  7.89 ms (+/- 0.312 ms)
</span></span><span class="line"><span class="ln">27</span><span class="cl">         Speedup: 3.32x
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">============================================================</span></span></code></pre></div><p><strong>結果分析</strong>：</p>
<table>
  <thead>
      <tr>
          <th>內容大小</th>
          <th>Python</th>
          <th>Cython</th>
          <th>加速比</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>1,000 行</td>
          <td>0.52 ms</td>
          <td>0.20 ms</td>
          <td>2.6x</td>
      </tr>
      <tr>
          <td>5,000 行</td>
          <td>2.62 ms</td>
          <td>0.89 ms</td>
          <td>2.9x</td>
      </tr>
      <tr>
          <td>10,000 行</td>
          <td>5.23 ms</td>
          <td>1.71 ms</td>
          <td>3.1x</td>
      </tr>
      <tr>
          <td>50,000 行</td>
          <td>26.2 ms</td>
          <td>7.89 ms</td>
          <td>3.3x</td>
      </tr>
  </tbody>
</table>
<p>觀察：</p>
<ul>
<li>加速比隨著資料量增加而提高</li>
<li>主要效能提升來自迴圈優化和型別化變數</li>
<li>正則表達式仍然是瓶頸（Cython 無法加速 <code>re</code> 模組本身）</li>
</ul>
<h2 id="設計權衡">設計權衡</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>純 Python</th>
          <th>Cython</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>開發速度</strong></td>
          <td>快，即寫即用</td>
          <td>中，需要編譯步驟</td>
      </tr>
      <tr>
          <td><strong>執行速度</strong></td>
          <td>基準</td>
          <td>2-5x 加速</td>
      </tr>
      <tr>
          <td><strong>除錯難度</strong></td>
          <td>低，標準 Python 工具</td>
          <td>中，需要看生成的 C 碼</td>
      </tr>
      <tr>
          <td><strong>部署複雜度</strong></td>
          <td>簡單，純 Python</td>
          <td>需要編譯環境或預編譯 wheel</td>
      </tr>
      <tr>
          <td><strong>可維護性</strong></td>
          <td>高</td>
          <td>中，需要了解 Cython 語法</td>
      </tr>
      <tr>
          <td><strong>IDE 支援</strong></td>
          <td>完整</td>
          <td>部分（.pyx 支援有限）</td>
      </tr>
      <tr>
          <td><strong>跨平台</strong></td>
          <td>天生跨平台</td>
          <td>需要為每個平台編譯</td>
      </tr>
  </tbody>
</table>
<h2 id="進階優化使用-c-正則表達式">進階優化：使用 C 正則表達式</h2>
<p>如果需要更高的效能，可以考慮使用 C 語言的正則表達式庫。以下是使用 PCRE2 的範例：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># advanced_parser.pyx</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="sd">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="sd">Advanced parser using PCRE2 C library for maximum performance.
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="sd">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="sd">Requires: libpcre2-dev (Ubuntu) or pcre2 (macOS Homebrew)
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="sd">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="k">cdef</span> <span class="kr">extern</span> <span class="k">from</span> <span class="s">&#34;pcre2.h&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="c"># PCRE2 declarations...</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">pass</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c"># This is an advanced topic, see PCRE2 documentation for details</span></span></span></code></pre></div><p>不過，對於大多數使用情境，Python 的 <code>re</code> 模組配合 Cython 優化的迴圈已經足夠。</p>
<h2 id="什麼時候該用-cython">什麼時候該用 Cython？</h2>
<h3 id="適合使用">適合使用</h3>
<ul>
<li>熱點程式碼已經用 profiler 確認</li>
<li>需要 2x 以上的效能提升</li>
<li>程式碼相對穩定，不常變動</li>
<li>團隊有能力維護 Cython 程式碼</li>
<li>可以接受編譯步驟</li>
</ul>
<h3 id="不建議使用">不建議使用</h3>
<ul>
<li>效能瓶頸在 I/O（網路、磁碟）</li>
<li>程式碼還在頻繁迭代中</li>
<li>跨平台部署且沒有 CI/CD 支援</li>
<li>團隊對 C 語言不熟悉</li>
<li>效能提升不到 2x</li>
</ul>
<h3 id="替代方案考量">替代方案考量</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">如果 Cython 不適合你的情境，考慮：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">1. PyPy
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">   - 無需修改程式碼
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">   - JIT 編譯帶來 5-10x 加速
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">   - 但相容性問題較多
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">2. Numba
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">   - 針對數值計算優化
</span></span><span class="line"><span class="ln">10</span><span class="cl">   - 使用裝飾器即可加速
</span></span><span class="line"><span class="ln">11</span><span class="cl">   - 但僅支援部分 Python 語法
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">3. 演算法優化
</span></span><span class="line"><span class="ln">14</span><span class="cl">   - 先檢查是否有更好的演算法
</span></span><span class="line"><span class="ln">15</span><span class="cl">   - 減少不必要的記憶體分配
</span></span><span class="line"><span class="ln">16</span><span class="cl">   - 使用更高效的資料結構</span></span></code></pre></div><h2 id="練習">練習</h2>
<h3 id="基礎練習">基礎練習</h3>
<p>將以下純 Python 函式轉換為 Cython：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># exercise_1.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">def</span> <span class="nf">count_words</span><span class="p">(</span><span class="n">text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Count word frequencies in text.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">words</span> <span class="o">=</span> <span class="n">text</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span><span class="o">.</span><span class="n">split</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">counts</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="k">for</span> <span class="n">word</span> <span class="ow">in</span> <span class="n">words</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="n">word</span> <span class="o">=</span> <span class="n">word</span><span class="o">.</span><span class="n">strip</span><span class="p">(</span><span class="s1">&#39;.,!?;:&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="k">if</span> <span class="n">word</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">            <span class="n">counts</span><span class="p">[</span><span class="n">word</span><span class="p">]</span> <span class="o">=</span> <span class="n">counts</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">word</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">return</span> <span class="n">counts</span></span></span></code></pre></div><p>提示：</p>
<ol>
<li>建立 <code>exercise_1.pyx</code></li>
<li>為 <code>counts</code> 變數添加 <code>cdef dict</code> 宣告</li>
<li>為迴圈變數添加適當的型別宣告</li>
<li>考慮使用 <code>cdef</code> 輔助函式處理字串清理</li>
</ol>
<h3 id="進階練習">進階練習</h3>
<p>使用 cProfile 驗證 Cython 加速效果：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># exercise_2.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">cProfile</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span> <span class="nn">pstats</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">def</span> <span class="nf">profile_parsers</span><span class="p">(</span><span class="n">content</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Profile both Python and Cython parsers.&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="kn">from</span> <span class="nn">markdown_parser</span> <span class="kn">import</span> <span class="n">parse_markdown_links</span> <span class="k">as</span> <span class="n">cython_parse</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">python_parser</span> <span class="o">=</span> <span class="n">PythonMarkdownParser</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="c1"># Profile Python version</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=== Python Version ===&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="n">cProfile</span><span class="o">.</span><span class="n">runctx</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="s1">&#39;for _ in range(100): python_parser.parse_markdown_links(content)&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="nb">globals</span><span class="p">(),</span> <span class="nb">locals</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="s1">&#39;python_stats&#39;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="n">stats</span> <span class="o">=</span> <span class="n">pstats</span><span class="o">.</span><span class="n">Stats</span><span class="p">(</span><span class="s1">&#39;python_stats&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="n">stats</span><span class="o">.</span><span class="n">strip_dirs</span><span class="p">()</span><span class="o">.</span><span class="n">sort_stats</span><span class="p">(</span><span class="s1">&#39;cumulative&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">print_stats</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="c1"># Profile Cython version</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">=== Cython Version ===&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="n">cProfile</span><span class="o">.</span><span class="n">runctx</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="s1">&#39;for _ in range(100): cython_parse(content)&#39;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="nb">globals</span><span class="p">(),</span> <span class="nb">locals</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="s1">&#39;cython_stats&#39;</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="n">stats</span> <span class="o">=</span> <span class="n">pstats</span><span class="o">.</span><span class="n">Stats</span><span class="p">(</span><span class="s1">&#39;cython_stats&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="n">stats</span><span class="o">.</span><span class="n">strip_dirs</span><span class="p">()</span><span class="o">.</span><span class="n">sort_stats</span><span class="p">(</span><span class="s1">&#39;cumulative&#39;</span><span class="p">)</span><span class="o">.</span><span class="n">print_stats</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span></span></span></code></pre></div><h3 id="挑戰題">挑戰題</h3>
<p>比較不同型別宣告策略的效能影響：</p>
<ol>
<li><strong>無型別宣告</strong>：將 <code>.pyx</code> 當作純 Python 編譯</li>
<li><strong>部分型別宣告</strong>：只為迴圈變數添加型別</li>
<li><strong>完整型別宣告</strong>：為所有變數添加型別</li>
<li><strong>使用 LinkInfo 類別</strong> vs <strong>使用 dict</strong></li>
</ol>
<p>記錄每種策略的效能，並分析哪些優化帶來最大效益。</p>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://cython.readthedocs.io/">Cython 官方文件</a></li>
<li><a href="https://cython.readthedocs.io/en/latest/src/tutorial/cython_tutorial.html">Cython 最佳實踐</a></li>
<li><a href="https://cython.readthedocs.io/en/latest/src/userguide/numpy_tutorial.html">Cython 與 NumPy 整合</a></li>
<li><a href="https://cython.readthedocs.io/en/latest/src/userguide/debugging.html">Cython 產生的 C 程式碼分析</a></li>
</ul>
<hr>
<p><em>返回：<a href="/blog/python-advanced/05-c-extensions/case-studies/" data-link-title="案例研究" data-link-desc="基於 .claude/lib 實際程式碼的 C 擴展案例">案例研究</a></em>
<em>返回：<a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組四：用 C 擴展 Python</a></em></p>
]]></content:encoded></item><item><title>4.1 ctypes 與 cffi：動態綁定</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/ctypes-cffi/</link><pubDate>Tue, 20 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/ctypes-cffi/</guid><description>&lt;p>本章介紹如何使用 ctypes 和 cffi 動態載入和呼叫 C 函式庫。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>理解 FFI（Foreign Function Interface）的概念&lt;/li>
&lt;li>使用 ctypes 呼叫系統函式庫&lt;/li>
&lt;li>使用 cffi 的 ABI 和 API 模式&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="原理層什麼是-ffi">【原理層】什麼是 FFI？&lt;/h2>
&lt;h3 id="動態連結庫">動態連結庫&lt;/h3>
&lt;p>現代作業系統使用動態連結庫（Shared Library）來共享程式碼：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">不同平台的動態連結庫：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">├── Linux: .so (Shared Object)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">├── macOS: .dylib (Dynamic Library)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">└── Windows: .dll (Dynamic Link Library)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">優點：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">- 節省記憶體（多個程式共享同一份）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">- 更新方便（不需重新編譯主程式）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">- 模組化設計&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="ffi-的概念">FFI 的概念&lt;/h3>
&lt;p>FFI（Foreign Function Interface）是一種讓程式語言呼叫其他語言函式的機制：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Python 程式
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl"> ↓ FFI
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">┌───────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">│ C 函式庫 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">│ - libc.so │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">│ - libm.so │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">│ - 自訂 .so │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">9&lt;/span>&lt;span class="cl">└───────────────┘&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="ctypes-vs-cffi">ctypes vs cffi&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>特性&lt;/th>
 &lt;th>ctypes&lt;/th>
 &lt;th>cffi&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>來源&lt;/td>
 &lt;td>標準庫&lt;/td>
 &lt;td>第三方&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>設計&lt;/td>
 &lt;td>物件導向 API&lt;/td>
 &lt;td>C 語法描述&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>效能&lt;/td>
 &lt;td>較慢&lt;/td>
 &lt;td>較快（API 模式）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>學習曲線&lt;/td>
 &lt;td>較平緩&lt;/td>
 &lt;td>需要 C 語法知識&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>PyPy 支援&lt;/td>
 &lt;td>有限&lt;/td>
 &lt;td>完整&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="設計層ctypes-基礎">【設計層】ctypes 基礎&lt;/h2>
&lt;h3 id="載入動態連結庫">載入動態連結庫&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes.util&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 1：直接載入&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># Linux/macOS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;libc.so.6&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># Linux&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;libc.dylib&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># macOS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># Windows&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="n">msvcrt&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;msvcrt&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 2：使用 find_library（推薦，跨平台）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">ctypes.util&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">find_library&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="n">libc_path&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">find_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;c&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;libc 路徑: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">libc_path&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">libc_path&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 3：載入自訂函式庫&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="n">mylib&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;./mylib.so&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="c-型別對應">C 型別對應&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="c1"># 基本型別對應&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="s2">C 型別 ctypes 型別 Python 型別
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2">─────────────────────────────────────────────────
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2">char c_char bytes (長度 1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2">wchar_t c_wchar str (長度 1)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2">char * c_char_p bytes 或 None
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2">wchar_t * c_wchar_p str 或 None
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="s2">int c_int int
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="s2">unsigned int c_uint int
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="s2">long c_long int
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="s2">unsigned long c_ulong int
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="s2">long long c_longlong int
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="s2">float c_float float
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="s2">double c_double float
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="s2">void * c_void_p int 或 None
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="c1"># 範例：設定函式的參數和回傳型別&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">util&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;c&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="c1"># strlen 函式：size_t strlen(const char *s)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strlen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_char_p&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strlen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_size_t&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strlen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;Hello, World!&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;字串長度: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 13&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="指標操作">指標操作&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="c1"># 建立指標&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">42&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="n">ptr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pointer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 指向 x 的指標&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;值: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ptr&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">contents&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 42&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># 修改值&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="n">ptr&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">contents&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">100&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;新值: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 100&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="c1"># 指標型別&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="n">IntPtr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">POINTER&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="c1"># 空指標&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="n">null_ptr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">IntPtr&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;是否為空: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="ow">not&lt;/span> &lt;span class="n">null_ptr&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="c1"># byref：輕量級的指標傳遞（不建立完整指標物件）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">example_with_byref&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="n">value&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 假設某函式需要 int* 參數&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="c1"># some_func(ctypes.byref(value))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="結構體與聯合">結構體與聯合&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="c1"># 定義結構體&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Structure&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="n">_fields_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;x&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_double&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;y&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_double&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="c1"># 使用結構體&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="n">p&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">3.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mf">4.0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Point: (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">p&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="c1"># 巢狀結構體&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Rectangle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Structure&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="n">_fields_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;top_left&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;bottom_right&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="n">rect&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Rectangle&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">Point&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">10&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;矩形: (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">rect&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">top_left&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">rect&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">top_left&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">) -&amp;gt; &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;(&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">rect&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">bottom_right&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">rect&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">bottom_right&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="c1"># 陣列&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="n">IntArray5&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">&lt;span class="n">arr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">IntArray5&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;陣列: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">arr&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">&lt;span class="c1"># 聯合（Union）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">IntOrFloat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Union&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="n">_fields_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;i&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;f&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_float&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl">&lt;span class="n">u&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">IntOrFloat&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl">&lt;span class="n">u&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">f&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">3.14&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;作為 float: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">u&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;作為 int: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">u&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 記憶體的整數解釋&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="實作層ctypes-實戰">【實作層】ctypes 實戰&lt;/h2>
&lt;h3 id="呼叫系統-api">呼叫系統 API&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes.util&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 取得 process ID（跨平台範例）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">name&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;posix&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">util&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;c&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="c1"># pid_t getpid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getpid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="n">pid&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getpid&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;PID (ctypes): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">pid&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;PID (os): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getpid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="c1"># 呼叫數學函式&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="n">libm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">util&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;m&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="c1"># double sqrt(double x)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="n">libm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sqrt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_double&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="n">libm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sqrt&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_double&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sqrt&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mf">2.0&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;sqrt(2) = &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="回呼函式">回呼函式&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="c1"># 定義回呼函式型別&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># qsort 的比較函式：int (*compar)(const void *, const void *)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="n">CMPFUNC&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CFUNCTYPE&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 回傳型別&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_void_p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 參數 1&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_void_p&lt;/span> &lt;span class="c1"># 參數 2&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">py_compare&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;Python 比較函式&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 將 void* 轉換為 int*&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="n">a_val&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cast&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">POINTER&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">contents&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="n">b_val&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cast&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">POINTER&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>&lt;span class="p">))&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">contents&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">a_val&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">b_val&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="c1"># 包裝為 C 回呼&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="n">c_compare&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">CMPFUNC&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">py_compare&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="c1"># 使用 qsort&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">util&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;c&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="c1"># void qsort(void *base, size_t nmemb, size_t size,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="c1"># int (*compar)(const void *, const void *))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="n">IntArray&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">5&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">&lt;span class="n">arr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">IntArray&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">5&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">8&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">9&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;排序前: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">arr&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">&lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">qsort&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="n">arr&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># base&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl"> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">arr&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1"># nmemb&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sizeof&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="c1"># size&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="n">c_compare&lt;/span> &lt;span class="c1"># compar&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;排序後: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">arr&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="處理字串">處理字串&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">util&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;c&amp;#34;&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 注意：Python 3 的字串是 unicode&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="c1"># ctypes 的 c_char_p 需要 bytes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="c1"># 錯誤示範&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1"># libc.strlen(&amp;#34;Hello&amp;#34;) # TypeError&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1"># 正確做法&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strlen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;Hello&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;長度: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="c1"># 建立可修改的字串緩衝區&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="n">buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_string_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;Hello&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">20&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;原始: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="c1"># strcpy：複製字串&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strcpy&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;World&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;複製後: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="c1"># 處理 wchar_t（寬字元）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="c1"># wchar_t *wcscat(wchar_t *dest, const wchar_t *src)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="nb">hasattr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">libc&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;wcscat&amp;#39;&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="n">wbuffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_unicode_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Hello, &amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">50&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">wcscat&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">wbuffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s2">&amp;#34;World!&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;寬字串: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">wbuffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="設計層cffi-基礎">【設計層】cffi 基礎&lt;/h2>
&lt;h3 id="安裝與基本使用">安裝與基本使用&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">pip install cffi&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>




&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">cffi&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">FFI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="n">ffi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">FFI&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># ABI 模式：動態載入，不需編譯&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="n">ffi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cdef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2"> int strlen(const char *s);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2"> double sqrt(double x);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1"># 載入函式庫&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ffi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dlopen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kc">None&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># None = 載入預設 C 函式庫&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="c1"># 呼叫函式&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strlen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">b&lt;/span>&lt;span class="s2">&amp;#34;Hello, cffi!&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;strlen: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="abi-模式-vs-api-模式">ABI 模式 vs API 模式&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">cffi&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">FFI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="c1"># ========== ABI 模式 ==========&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 優點：簡單，不需編譯器&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 缺點：效能較差，型別檢查較弱&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="n">ffi_abi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">FFI&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="n">ffi_abi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cdef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> double sin(double x);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2"> double cos(double x);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="n">libm&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ffi_abi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">dlopen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;m&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="c1"># 或 None 使用預設&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">math&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;sin(π/2) = &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">libm&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">sin&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">math&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">pi&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="c1"># ========== API 模式 ==========&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="c1"># 優點：效能好，完整型別檢查&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="c1"># 缺點：需要編譯器&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="n">ffi_api&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">FFI&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="n">ffi_api&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cdef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="s2"> double compute_something(double x, double y);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="c1"># 設定原始碼（會編譯成擴展模組）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">&lt;span class="n">ffi_api&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">set_source&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;_example&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="s2"> double compute_something(double x, double y) {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">&lt;span class="s2"> return x * x + y * y;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">&lt;span class="s2"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl">&lt;span class="c1"># 編譯（通常在 setup.py 中執行）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">&lt;span class="c1"># ffi_api.compile()&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="cffi-的型別系統">cffi 的型別系統&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">cffi&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">FFI&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="n">ffi&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">FFI&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="c1"># 定義結構體&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="n">ffi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">cdef&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2"> typedef struct {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2"> double x;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> double y;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2"> } Point;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="s2"> typedef struct {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="s2"> Point center;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="s2"> double radius;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="s2"> } Circle;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="c1"># 建立結構體實例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="n">point&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ffi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Point *&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="n">point&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">x&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">3.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="n">point&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">y&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">4.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="c1"># 或者一次初始化&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="n">point2&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ffi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Point *&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;x&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">1.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;y&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">2.0&lt;/span>&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="c1"># 巢狀結構體&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">&lt;span class="n">circle&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ffi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Circle *&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;center&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="s1">&amp;#39;x&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">0.0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;y&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">0.0&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;radius&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="mf">5.0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">&lt;span class="p">})&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;圓心: (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">circle&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">center&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">x&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">circle&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">center&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">y&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;半徑: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">circle&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">radius&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl">&lt;span class="c1"># 陣列&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">&lt;span class="n">arr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ffi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;int[5]&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">4&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">5&lt;/span>&lt;span class="p">])&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl">&lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;陣列: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">list&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">arr&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl">&lt;span class="c1"># 動態大小陣列&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">&lt;span class="n">n&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">10&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl">&lt;span class="n">dynamic_arr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ffi&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;double[&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">]&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl">&lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl"> &lt;span class="n">dynamic_arr&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">i&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mf">0.5&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="實作層cffi-實戰">【實作層】cffi 實戰&lt;/h2>
&lt;h3 id="包裝簡單的-c-函式庫">包裝簡單的 C 函式庫&lt;/h3>
&lt;p>假設我們有一個簡單的 C 函式庫 &lt;code>mathutil.c&lt;/code>：&lt;/p></description><content:encoded><![CDATA[<p>本章介紹如何使用 ctypes 和 cffi 動態載入和呼叫 C 函式庫。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>理解 FFI（Foreign Function Interface）的概念</li>
<li>使用 ctypes 呼叫系統函式庫</li>
<li>使用 cffi 的 ABI 和 API 模式</li>
</ol>
<hr>
<h2 id="原理層什麼是-ffi">【原理層】什麼是 FFI？</h2>
<h3 id="動態連結庫">動態連結庫</h3>
<p>現代作業系統使用動態連結庫（Shared Library）來共享程式碼：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">不同平台的動態連結庫：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── Linux:   .so  (Shared Object)
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── macOS:   .dylib (Dynamic Library)
</span></span><span class="line"><span class="ln">4</span><span class="cl">└── Windows: .dll (Dynamic Link Library)
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl">優點：
</span></span><span class="line"><span class="ln">7</span><span class="cl">- 節省記憶體（多個程式共享同一份）
</span></span><span class="line"><span class="ln">8</span><span class="cl">- 更新方便（不需重新編譯主程式）
</span></span><span class="line"><span class="ln">9</span><span class="cl">- 模組化設計</span></span></code></pre></div><h3 id="ffi-的概念">FFI 的概念</h3>
<p>FFI（Foreign Function Interface）是一種讓程式語言呼叫其他語言函式的機制：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Python 程式
</span></span><span class="line"><span class="ln">2</span><span class="cl">    │
</span></span><span class="line"><span class="ln">3</span><span class="cl">    ↓ FFI
</span></span><span class="line"><span class="ln">4</span><span class="cl">┌───────────────┐
</span></span><span class="line"><span class="ln">5</span><span class="cl">│  C 函式庫     │
</span></span><span class="line"><span class="ln">6</span><span class="cl">│  - libc.so    │
</span></span><span class="line"><span class="ln">7</span><span class="cl">│  - libm.so    │
</span></span><span class="line"><span class="ln">8</span><span class="cl">│  - 自訂 .so   │
</span></span><span class="line"><span class="ln">9</span><span class="cl">└───────────────┘</span></span></code></pre></div><h3 id="ctypes-vs-cffi">ctypes vs cffi</h3>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th>ctypes</th>
          <th>cffi</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>來源</td>
          <td>標準庫</td>
          <td>第三方</td>
      </tr>
      <tr>
          <td>設計</td>
          <td>物件導向 API</td>
          <td>C 語法描述</td>
      </tr>
      <tr>
          <td>效能</td>
          <td>較慢</td>
          <td>較快（API 模式）</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>較平緩</td>
          <td>需要 C 語法知識</td>
      </tr>
      <tr>
          <td>PyPy 支援</td>
          <td>有限</td>
          <td>完整</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="設計層ctypes-基礎">【設計層】ctypes 基礎</h2>
<h3 id="載入動態連結庫">載入動態連結庫</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes.util</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 方法 1：直接載入</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># Linux/macOS</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">libc</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="s2">&#34;libc.so.6&#34;</span><span class="p">)</span>  <span class="c1"># Linux</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">libc</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="s2">&#34;libc.dylib&#34;</span><span class="p">)</span>  <span class="c1"># macOS</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># Windows</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="n">msvcrt</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="s2">&#34;msvcrt&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># 方法 2：使用 find_library（推薦，跨平台）</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="kn">from</span> <span class="nn">ctypes.util</span> <span class="kn">import</span> <span class="n">find_library</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">libc_path</span> <span class="o">=</span> <span class="n">find_library</span><span class="p">(</span><span class="s2">&#34;c&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;libc 路徑: </span><span class="si">{</span><span class="n">libc_path</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="n">libc</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="n">libc_path</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1"># 方法 3：載入自訂函式庫</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="n">mylib</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="s2">&#34;./mylib.so&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="c-型別對應">C 型別對應</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 基本型別對應</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s2">C 型別           ctypes 型別        Python 型別
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">─────────────────────────────────────────────────
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">char             c_char            bytes (長度 1)
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">wchar_t          c_wchar           str (長度 1)
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">char *           c_char_p          bytes 或 None
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">wchar_t *        c_wchar_p         str 或 None
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">int              c_int             int
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">unsigned int     c_uint            int
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">long             c_long            int
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">unsigned long    c_ulong           int
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">long long        c_longlong        int
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">float            c_float           float
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s2">double           c_double          float
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="s2">void *           c_void_p          int 或 None
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c1"># 範例：設定函式的參數和回傳型別</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="n">libc</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">find_library</span><span class="p">(</span><span class="s2">&#34;c&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="c1"># strlen 函式：size_t strlen(const char *s)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_size_t</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="p">(</span><span class="sa">b</span><span class="s2">&#34;Hello, World!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;字串長度: </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>  <span class="c1"># 13</span></span></span></code></pre></div><h3 id="指標操作">指標操作</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 建立指標</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">x</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">(</span><span class="mi">42</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">ptr</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">pointer</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>  <span class="c1"># 指向 x 的指標</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;值: </span><span class="si">{</span><span class="n">ptr</span><span class="o">.</span><span class="n">contents</span><span class="o">.</span><span class="n">value</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>  <span class="c1"># 42</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 修改值</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="n">ptr</span><span class="o">.</span><span class="n">contents</span><span class="o">.</span><span class="n">value</span> <span class="o">=</span> <span class="mi">100</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;新值: </span><span class="si">{</span><span class="n">x</span><span class="o">.</span><span class="n">value</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>  <span class="c1"># 100</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># 指標型別</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">IntPtr</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">POINTER</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1"># 空指標</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="n">null_ptr</span> <span class="o">=</span> <span class="n">IntPtr</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;是否為空: </span><span class="si">{</span><span class="ow">not</span> <span class="n">null_ptr</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>  <span class="c1"># True</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c1"># byref：輕量級的指標傳遞（不建立完整指標物件）</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="k">def</span> <span class="nf">example_with_byref</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="n">value</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="c1"># 假設某函式需要 int* 參數</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="c1"># some_func(ctypes.byref(value))</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="k">return</span> <span class="n">value</span><span class="o">.</span><span class="n">value</span></span></span></code></pre></div><h3 id="結構體與聯合">結構體與聯合</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 定義結構體</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">class</span> <span class="nc">Point</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">Structure</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;x&#34;</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_double</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;y&#34;</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_double</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 使用結構體</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">p</span> <span class="o">=</span> <span class="n">Point</span><span class="p">(</span><span class="mf">3.0</span><span class="p">,</span> <span class="mf">4.0</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Point: (</span><span class="si">{</span><span class="n">p</span><span class="o">.</span><span class="n">x</span><span class="si">}</span><span class="s2">, </span><span class="si">{</span><span class="n">p</span><span class="o">.</span><span class="n">y</span><span class="si">}</span><span class="s2">)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"># 巢狀結構體</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="k">class</span> <span class="nc">Rectangle</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">Structure</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;top_left&#34;</span><span class="p">,</span> <span class="n">Point</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;bottom_right&#34;</span><span class="p">,</span> <span class="n">Point</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="n">rect</span> <span class="o">=</span> <span class="n">Rectangle</span><span class="p">(</span><span class="n">Point</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">),</span> <span class="n">Point</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;矩形: (</span><span class="si">{</span><span class="n">rect</span><span class="o">.</span><span class="n">top_left</span><span class="o">.</span><span class="n">x</span><span class="si">}</span><span class="s2">, </span><span class="si">{</span><span class="n">rect</span><span class="o">.</span><span class="n">top_left</span><span class="o">.</span><span class="n">y</span><span class="si">}</span><span class="s2">) -&gt; &#34;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">      <span class="sa">f</span><span class="s2">&#34;(</span><span class="si">{</span><span class="n">rect</span><span class="o">.</span><span class="n">bottom_right</span><span class="o">.</span><span class="n">x</span><span class="si">}</span><span class="s2">, </span><span class="si">{</span><span class="n">rect</span><span class="o">.</span><span class="n">bottom_right</span><span class="o">.</span><span class="n">y</span><span class="si">}</span><span class="s2">)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="c1"># 陣列</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="n">IntArray5</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span> <span class="o">*</span> <span class="mi">5</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="n">arr</span> <span class="o">=</span> <span class="n">IntArray5</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;陣列: </span><span class="si">{</span><span class="nb">list</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="c1"># 聯合（Union）</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="k">class</span> <span class="nc">IntOrFloat</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">Union</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;i&#34;</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;f&#34;</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_float</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="n">u</span> <span class="o">=</span> <span class="n">IntOrFloat</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="n">u</span><span class="o">.</span><span class="n">f</span> <span class="o">=</span> <span class="mf">3.14</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;作為 float: </span><span class="si">{</span><span class="n">u</span><span class="o">.</span><span class="n">f</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;作為 int: </span><span class="si">{</span><span class="n">u</span><span class="o">.</span><span class="n">i</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>  <span class="c1"># 記憶體的整數解釋</span></span></span></code></pre></div><hr>
<h2 id="實作層ctypes-實戰">【實作層】ctypes 實戰</h2>
<h3 id="呼叫系統-api">呼叫系統 API</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes.util</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 取得 process ID（跨平台範例）</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">if</span> <span class="n">os</span><span class="o">.</span><span class="n">name</span> <span class="o">==</span> <span class="s1">&#39;posix&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">find_library</span><span class="p">(</span><span class="s2">&#34;c&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="c1"># pid_t getpid(void)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getpid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">pid</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">getpid</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;PID (ctypes): </span><span class="si">{</span><span class="n">pid</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;PID (os): </span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="c1"># 呼叫數學函式</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="n">libm</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">find_library</span><span class="p">(</span><span class="s2">&#34;m&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c1"># double sqrt(double x)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="n">libm</span><span class="o">.</span><span class="n">sqrt</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_double</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="n">libm</span><span class="o">.</span><span class="n">sqrt</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_double</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="n">result</span> <span class="o">=</span> <span class="n">libm</span><span class="o">.</span><span class="n">sqrt</span><span class="p">(</span><span class="mf">2.0</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;sqrt(2) = </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="回呼函式">回呼函式</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 定義回呼函式型別</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># qsort 的比較函式：int (*compar)(const void *, const void *)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">CMPFUNC</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CFUNCTYPE</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">,</span>      <span class="c1"># 回傳型別</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">ctypes</span><span class="o">.</span><span class="n">c_void_p</span><span class="p">,</span>   <span class="c1"># 參數 1</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">ctypes</span><span class="o">.</span><span class="n">c_void_p</span>    <span class="c1"># 參數 2</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="k">def</span> <span class="nf">py_compare</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Python 比較函式&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="c1"># 將 void* 轉換為 int*</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="n">a_val</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">cast</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">POINTER</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">))</span><span class="o">.</span><span class="n">contents</span><span class="o">.</span><span class="n">value</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">b_val</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">cast</span><span class="p">(</span><span class="n">b</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">POINTER</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">))</span><span class="o">.</span><span class="n">contents</span><span class="o">.</span><span class="n">value</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="k">return</span> <span class="n">a_val</span> <span class="o">-</span> <span class="n">b_val</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c1"># 包裝為 C 回呼</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="n">c_compare</span> <span class="o">=</span> <span class="n">CMPFUNC</span><span class="p">(</span><span class="n">py_compare</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c1"># 使用 qsort</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="n">libc</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">find_library</span><span class="p">(</span><span class="s2">&#34;c&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="c1"># void qsort(void *base, size_t nmemb, size_t size,</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="c1">#            int (*compar)(const void *, const void *))</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="n">IntArray</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span> <span class="o">*</span> <span class="mi">5</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="n">arr</span> <span class="o">=</span> <span class="n">IntArray</span><span class="p">(</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">9</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;排序前: </span><span class="si">{</span><span class="nb">list</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">
</span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="n">libc</span><span class="o">.</span><span class="n">qsort</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="n">arr</span><span class="p">,</span>                          <span class="c1"># base</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="nb">len</span><span class="p">(</span><span class="n">arr</span><span class="p">),</span>                     <span class="c1"># nmemb</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">ctypes</span><span class="o">.</span><span class="n">sizeof</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">),</span>  <span class="c1"># size</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="n">c_compare</span>                     <span class="c1"># compar</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">
</span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;排序後: </span><span class="si">{</span><span class="nb">list</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="處理字串">處理字串</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">libc</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">find_library</span><span class="p">(</span><span class="s2">&#34;c&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 注意：Python 3 的字串是 unicode</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># ctypes 的 c_char_p 需要 bytes</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 錯誤示範</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># libc.strlen(&#34;Hello&#34;)  # TypeError</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># 正確做法</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="p">(</span><span class="sa">b</span><span class="s2">&#34;Hello&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;長度: </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="c1"># 建立可修改的字串緩衝區</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="n">buffer</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">create_string_buffer</span><span class="p">(</span><span class="sa">b</span><span class="s2">&#34;Hello&#34;</span><span class="p">,</span> <span class="mi">20</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;原始: </span><span class="si">{</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1"># strcpy：複製字串</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="n">libc</span><span class="o">.</span><span class="n">strcpy</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="sa">b</span><span class="s2">&#34;World&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;複製後: </span><span class="si">{</span><span class="n">buffer</span><span class="o">.</span><span class="n">value</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="c1"># 處理 wchar_t（寬字元）</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="c1"># wchar_t *wcscat(wchar_t *dest, const wchar_t *src)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">libc</span><span class="p">,</span> <span class="s1">&#39;wcscat&#39;</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">wbuffer</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">create_unicode_buffer</span><span class="p">(</span><span class="s2">&#34;Hello, &#34;</span><span class="p">,</span> <span class="mi">50</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">wcscat</span><span class="p">(</span><span class="n">wbuffer</span><span class="p">,</span> <span class="s2">&#34;World!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;寬字串: </span><span class="si">{</span><span class="n">wbuffer</span><span class="o">.</span><span class="n">value</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><hr>
<h2 id="設計層cffi-基礎">【設計層】cffi 基礎</h2>
<h3 id="安裝與基本使用">安裝與基本使用</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">pip install cffi</span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">from</span> <span class="nn">cffi</span> <span class="kn">import</span> <span class="n">FFI</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">ffi</span> <span class="o">=</span> <span class="n">FFI</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># ABI 模式：動態載入，不需編譯</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">ffi</span><span class="o">.</span><span class="n">cdef</span><span class="p">(</span><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">    int strlen(const char *s);
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">    double sqrt(double x);
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># 載入函式庫</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">libc</span> <span class="o">=</span> <span class="n">ffi</span><span class="o">.</span><span class="n">dlopen</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>  <span class="c1"># None = 載入預設 C 函式庫</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"># 呼叫函式</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="p">(</span><span class="sa">b</span><span class="s2">&#34;Hello, cffi!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;strlen: </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="abi-模式-vs-api-模式">ABI 模式 vs API 模式</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">from</span> <span class="nn">cffi</span> <span class="kn">import</span> <span class="n">FFI</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># ========== ABI 模式 ==========</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 優點：簡單，不需編譯器</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 缺點：效能較差，型別檢查較弱</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">ffi_abi</span> <span class="o">=</span> <span class="n">FFI</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">ffi_abi</span><span class="o">.</span><span class="n">cdef</span><span class="p">(</span><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">    double sin(double x);
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">    double cos(double x);
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">libm</span> <span class="o">=</span> <span class="n">ffi_abi</span><span class="o">.</span><span class="n">dlopen</span><span class="p">(</span><span class="s2">&#34;m&#34;</span><span class="p">)</span>  <span class="c1"># 或 None 使用預設</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="kn">import</span> <span class="nn">math</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;sin(π/2) = </span><span class="si">{</span><span class="n">libm</span><span class="o">.</span><span class="n">sin</span><span class="p">(</span><span class="n">math</span><span class="o">.</span><span class="n">pi</span> <span class="o">/</span> <span class="mi">2</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"># ========== API 模式 ==========</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c1"># 優點：效能好，完整型別檢查</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1"># 缺點：需要編譯器</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="n">ffi_api</span> <span class="o">=</span> <span class="n">FFI</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="n">ffi_api</span><span class="o">.</span><span class="n">cdef</span><span class="p">(</span><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="s2">    double compute_something(double x, double y);
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="c1"># 設定原始碼（會編譯成擴展模組）</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="n">ffi_api</span><span class="o">.</span><span class="n">set_source</span><span class="p">(</span><span class="s2">&#34;_example&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="s2">    double compute_something(double x, double y) {
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="s2">        return x * x + y * y;
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="s2">    }
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">
</span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="c1"># 編譯（通常在 setup.py 中執行）</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="c1"># ffi_api.compile()</span></span></span></code></pre></div><h3 id="cffi-的型別系統">cffi 的型別系統</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">from</span> <span class="nn">cffi</span> <span class="kn">import</span> <span class="n">FFI</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">ffi</span> <span class="o">=</span> <span class="n">FFI</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># 定義結構體</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">ffi</span><span class="o">.</span><span class="n">cdef</span><span class="p">(</span><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">    typedef struct {
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">        double x;
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">        double y;
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">    } Point;
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">    typedef struct {
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">        Point center;
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">        double radius;
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">    } Circle;
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c1"># 建立結構體實例</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="n">point</span> <span class="o">=</span> <span class="n">ffi</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&#34;Point *&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="n">point</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="mf">3.0</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="n">point</span><span class="o">.</span><span class="n">y</span> <span class="o">=</span> <span class="mf">4.0</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="c1"># 或者一次初始化</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="n">point2</span> <span class="o">=</span> <span class="n">ffi</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&#34;Point *&#34;</span><span class="p">,</span> <span class="p">{</span><span class="s1">&#39;x&#39;</span><span class="p">:</span> <span class="mf">1.0</span><span class="p">,</span> <span class="s1">&#39;y&#39;</span><span class="p">:</span> <span class="mf">2.0</span><span class="p">})</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="c1"># 巢狀結構體</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="n">circle</span> <span class="o">=</span> <span class="n">ffi</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&#34;Circle *&#34;</span><span class="p">,</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="s1">&#39;center&#39;</span><span class="p">:</span> <span class="p">{</span><span class="s1">&#39;x&#39;</span><span class="p">:</span> <span class="mf">0.0</span><span class="p">,</span> <span class="s1">&#39;y&#39;</span><span class="p">:</span> <span class="mf">0.0</span><span class="p">},</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="s1">&#39;radius&#39;</span><span class="p">:</span> <span class="mf">5.0</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="p">})</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;圓心: (</span><span class="si">{</span><span class="n">circle</span><span class="o">.</span><span class="n">center</span><span class="o">.</span><span class="n">x</span><span class="si">}</span><span class="s2">, </span><span class="si">{</span><span class="n">circle</span><span class="o">.</span><span class="n">center</span><span class="o">.</span><span class="n">y</span><span class="si">}</span><span class="s2">)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;半徑: </span><span class="si">{</span><span class="n">circle</span><span class="o">.</span><span class="n">radius</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">
</span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="c1"># 陣列</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="n">arr</span> <span class="o">=</span> <span class="n">ffi</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&#34;int[5]&#34;</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">])</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;陣列: </span><span class="si">{</span><span class="nb">list</span><span class="p">(</span><span class="n">arr</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">
</span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="c1"># 動態大小陣列</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="n">n</span> <span class="o">=</span> <span class="mi">10</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="n">dynamic_arr</span> <span class="o">=</span> <span class="n">ffi</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;double[</span><span class="si">{</span><span class="n">n</span><span class="si">}</span><span class="s2">]&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">    <span class="n">dynamic_arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">i</span> <span class="o">*</span> <span class="mf">0.5</span></span></span></code></pre></div><hr>
<h2 id="實作層cffi-實戰">【實作層】cffi 實戰</h2>
<h3 id="包裝簡單的-c-函式庫">包裝簡單的 C 函式庫</h3>
<p>假設我們有一個簡單的 C 函式庫 <code>mathutil.c</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// mathutil.c
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&lt;math.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="kt">double</span> <span class="nf">vector_length</span><span class="p">(</span><span class="kt">double</span> <span class="n">x</span><span class="p">,</span> <span class="kt">double</span> <span class="n">y</span><span class="p">,</span> <span class="kt">double</span> <span class="n">z</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">return</span> <span class="nf">sqrt</span><span class="p">(</span><span class="n">x</span><span class="o">*</span><span class="n">x</span> <span class="o">+</span> <span class="n">y</span><span class="o">*</span><span class="n">y</span> <span class="o">+</span> <span class="n">z</span><span class="o">*</span><span class="n">z</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="kt">int</span> <span class="nf">fibonacci</span><span class="p">(</span><span class="kt">int</span> <span class="n">n</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">)</span> <span class="k">return</span> <span class="n">n</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="kt">int</span> <span class="n">a</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">2</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;=</span> <span class="n">n</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="kt">int</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="n">a</span> <span class="o">=</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="n">b</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="k">return</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>使用 cffi 包裝：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># build_mathutil.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">from</span> <span class="nn">cffi</span> <span class="kn">import</span> <span class="n">FFI</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">ffi</span> <span class="o">=</span> <span class="n">FFI</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># 宣告要使用的函式</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="n">ffi</span><span class="o">.</span><span class="n">cdef</span><span class="p">(</span><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">    double vector_length(double x, double y, double z);
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">    int fibonacci(int n);
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># 設定原始碼</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="n">ffi</span><span class="o">.</span><span class="n">set_source</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="s2">&#34;_mathutil&#34;</span><span class="p">,</span>  <span class="c1"># 模組名稱</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">    #include &lt;math.h&gt;
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="s2">    double vector_length(double x, double y, double z) {
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="s2">        return sqrt(x*x + y*y + z*z);
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="s2">    }
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="s2">    int fibonacci(int n) {
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="s2">        if (n &lt;= 1) return n;
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="s2">        int a = 0, b = 1;
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="s2">        for (int i = 2; i &lt;= n; i++) {
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="s2">            int tmp = a + b;
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="s2">            a = b;
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="s2">            b = tmp;
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="s2">        }
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="s2">        return b;
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="s2">    }
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="n">libraries</span><span class="o">=</span><span class="p">[</span><span class="s1">&#39;m&#39;</span><span class="p">],</span>  <span class="c1"># 連結數學函式庫</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">
</span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="n">ffi</span><span class="o">.</span><span class="n">compile</span><span class="p">(</span><span class="n">verbose</span><span class="o">=</span><span class="kc">True</span><span class="p">)</span></span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 使用編譯後的模組</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="kn">from</span> <span class="nn">_mathutil</span> <span class="kn">import</span> <span class="n">ffi</span><span class="p">,</span> <span class="n">lib</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="n">length</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">vector_length</span><span class="p">(</span><span class="mf">1.0</span><span class="p">,</span> <span class="mf">2.0</span><span class="p">,</span> <span class="mf">2.0</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;向量長度: </span><span class="si">{</span><span class="n">length</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>  <span class="c1"># 3.0</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="n">fib_10</span> <span class="o">=</span> <span class="n">lib</span><span class="o">.</span><span class="n">fibonacci</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;fibonacci(10): </span><span class="si">{</span><span class="n">fib_10</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>  <span class="c1"># 55</span></span></span></code></pre></div><h3 id="回呼函式-1">回呼函式</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">from</span> <span class="nn">cffi</span> <span class="kn">import</span> <span class="n">FFI</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">ffi</span> <span class="o">=</span> <span class="n">FFI</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">ffi</span><span class="o">.</span><span class="n">cdef</span><span class="p">(</span><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    typedef int (*compare_func)(int, int);
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">    void custom_sort(int *arr, int size, compare_func cmp);
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="n">ffi</span><span class="o">.</span><span class="n">set_source</span><span class="p">(</span><span class="s2">&#34;_sort_example&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">    typedef int (*compare_func)(int, int);
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">    void custom_sort(int *arr, int size, compare_func cmp) {
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">        // 簡單的冒泡排序
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">        for (int i = 0; i &lt; size - 1; i++) {
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s2">            for (int j = 0; j &lt; size - i - 1; j++) {
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="s2">                if (cmp(arr[j], arr[j+1]) &gt; 0) {
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="s2">                    int tmp = arr[j];
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="s2">                    arr[j] = arr[j+1];
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="s2">                    arr[j+1] = tmp;
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="s2">                }
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="s2">            }
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="s2">        }
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="s2">    }
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="c1"># 編譯後使用</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="c1"># from _sort_example import ffi, lib</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="c1"># @ffi.callback(&#34;int(int, int)&#34;)</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="c1"># def py_compare(a, b):</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="c1">#     return a - b</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">
</span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="c1"># arr = ffi.new(&#34;int[5]&#34;, [5, 2, 8, 1, 9])</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="c1"># lib.custom_sort(arr, 5, py_compare)</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="c1"># print(list(arr))  # [1, 2, 5, 8, 9]</span></span></span></code></pre></div><h3 id="記憶體管理">記憶體管理</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">from</span> <span class="nn">cffi</span> <span class="kn">import</span> <span class="n">FFI</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="n">ffi</span> <span class="o">=</span> <span class="n">FFI</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># ffi.new() 分配的記憶體會自動管理</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">data</span> <span class="o">=</span> <span class="n">ffi</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="s2">&#34;int[100]&#34;</span><span class="p">)</span>  <span class="c1"># 自動回收</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 需要手動管理的情況</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">ffi</span><span class="o">.</span><span class="n">cdef</span><span class="p">(</span><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">    void *malloc(size_t size);
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">    void free(void *ptr);
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">libc</span> <span class="o">=</span> <span class="n">ffi</span><span class="o">.</span><span class="n">dlopen</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1"># 手動分配</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="n">ptr</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">malloc</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="k">if</span> <span class="n">ptr</span> <span class="o">!=</span> <span class="n">ffi</span><span class="o">.</span><span class="n">NULL</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="c1"># 使用記憶體...</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="c1"># 必須手動釋放</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">free</span><span class="p">(</span><span class="n">ptr</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="c1"># 使用 ffi.gc() 自動管理外部分配的記憶體</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="k">def</span> <span class="nf">auto_managed_alloc</span><span class="p">(</span><span class="n">size</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">ptr</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">malloc</span><span class="p">(</span><span class="n">size</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="k">if</span> <span class="n">ptr</span> <span class="o">==</span> <span class="n">ffi</span><span class="o">.</span><span class="n">NULL</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="k">raise</span> <span class="ne">MemoryError</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="c1"># 設定 finalizer，當 Python 物件被回收時自動呼叫</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="k">return</span> <span class="n">ffi</span><span class="o">.</span><span class="n">gc</span><span class="p">(</span><span class="n">ptr</span><span class="p">,</span> <span class="n">libc</span><span class="o">.</span><span class="n">free</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="n">managed_ptr</span> <span class="o">=</span> <span class="n">auto_managed_alloc</span><span class="p">(</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="c1"># 不需要手動 free，Python GC 會處理</span></span></span></code></pre></div><hr>
<h2 id="選擇指南ctypes-vs-cffi">【選擇指南】ctypes vs cffi</h2>
<h3 id="決策流程">決策流程</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">需要呼叫 C 函式庫？
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">│
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├── 只需要簡單呼叫系統 API
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">│   └── ctypes（標準庫，不需額外安裝）
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">│
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">├── 需要包裝複雜的 C 函式庫
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">│   └── cffi API 模式（更好的型別檢查）
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">│
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">├── 在 PyPy 上執行
</span></span><span class="line"><span class="ln">10</span><span class="cl">│   └── cffi（PyPy 原生支援）
</span></span><span class="line"><span class="ln">11</span><span class="cl">│
</span></span><span class="line"><span class="ln">12</span><span class="cl">└── 效能要求高
</span></span><span class="line"><span class="ln">13</span><span class="cl">    └── cffi API 模式 或 考慮 Cython/pybind11</span></span></code></pre></div><h3 id="效能比較">效能比較</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">timeit</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 測試函式呼叫開銷</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">setup_ctypes</span> <span class="o">=</span> <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s2">import ctypes
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">import ctypes.util
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">libm = ctypes.CDLL(ctypes.util.find_library(&#34;m&#34;))
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">libm.sqrt.argtypes = [ctypes.c_double]
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">libm.sqrt.restype = ctypes.c_double
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">setup_cffi</span> <span class="o">=</span> <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">from cffi import FFI
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">ffi = FFI()
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">ffi.cdef(&#34;double sqrt(double x);&#34;)
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">libm = ffi.dlopen(&#34;m&#34;)
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1"># 結果（僅供參考，實際數據取決於環境）</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c1"># ctypes: ~0.3 μs per call</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c1"># cffi ABI: ~0.2 μs per call</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="c1"># cffi API: ~0.05 μs per call</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="c1"># 原生 Python math.sqrt: ~0.02 μs per call</span></span></span></code></pre></div><h3 id="常見錯誤與除錯">常見錯誤與除錯</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 錯誤 1：忘記設定 argtypes/restype</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">libc</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">find_library</span><span class="p">(</span><span class="s2">&#34;c&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># result = libc.strlen(&#34;hello&#34;)  # 可能 crash 或回傳錯誤值</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 正確做法</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_size_t</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="p">(</span><span class="sa">b</span><span class="s2">&#34;hello&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># 錯誤 2：傳遞 Python str 而非 bytes</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># libc.strlen(&#34;hello&#34;)  # TypeError</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="c1"># 錯誤 3：回呼函式被垃圾回收</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="n">CALLBACK</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CFUNCTYPE</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="k">def</span> <span class="nf">bad_example</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="mi">2</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="n">c_callback</span> <span class="o">=</span> <span class="n">CALLBACK</span><span class="p">(</span><span class="n">callback</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="c1"># 如果這裡把 c_callback 傳給 C，然後函式結束</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="c1"># c_callback 可能被回收，C 呼叫時會 crash</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="k">return</span> <span class="n">c_callback</span>  <span class="c1"># 必須保持參考</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">
</span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="c1"># 正確做法：保持回呼的參考</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="n">_callbacks</span> <span class="o">=</span> <span class="p">[]</span>  <span class="c1"># 全域列表保持參考</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="k">def</span> <span class="nf">safe_example</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">        <span class="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="mi">2</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">c_callback</span> <span class="o">=</span> <span class="n">CALLBACK</span><span class="p">(</span><span class="n">callback</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="n">_callbacks</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">c_callback</span><span class="p">)</span>  <span class="c1"># 保持參考</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="k">return</span> <span class="n">c_callback</span></span></span></code></pre></div><hr>
<h2 id="思考題">思考題</h2>
<ol>
<li>為什麼 cffi 的 API 模式比 ABI 模式快？這與 Python 的執行模型有什麼關係？</li>
<li>在什麼情況下，使用 ctypes/cffi 會比重新用 Python 實現更好？</li>
<li>如何安全地處理 C 函式庫中的記憶體分配？</li>
</ol>
<h2 id="實作練習">實作練習</h2>
<ol>
<li>使用 ctypes 包裝 <code>time.h</code> 中的 <code>time()</code> 和 <code>localtime()</code> 函式</li>
<li>使用 cffi 包裝一個簡單的數學函式庫，提供矩陣乘法功能</li>
<li>比較 ctypes、cffi ABI 模式、cffi API 模式在大量函式呼叫時的效能差異</li>
</ol>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://docs.python.org/3/library/ctypes.html">Python ctypes 官方文件</a></li>
<li><a href="https://cffi.readthedocs.io/">CFFI 官方文件</a></li>
<li><a href="https://realpython.com/python-bindings-overview/">Real Python - Python Bindings</a></li>
</ul>
<hr>
<p>下一章：<a href="/blog/python-advanced/05-c-extensions/cython/" data-link-title="4.2 Cython：Python 語法的 C 速度" data-link-desc="使用 Cython 加速 Python 程式碼">Cython</a></p>
]]></content:encoded></item><item><title>案例：使用 ctypes 呼叫系統 API</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/ctypes-system-call/</link><pubDate>Wed, 21 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/ctypes-system-call/</guid><description>&lt;p>本案例展示如何使用 ctypes 直接呼叫系統 API，處理 Python 標準庫未提供的底層功能。&lt;/p>
&lt;h2 id="先備知識">先備知識&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/ctypes-cffi/" data-link-title="4.1 ctypes 與 cffi：動態綁定" data-link-desc="使用 ctypes 和 cffi 呼叫 C 函式庫">4.1 ctypes 與 cffi：動態綁定&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="問題背景">問題背景&lt;/h2>
&lt;h3 id="為什麼需要直接呼叫系統-api">為什麼需要直接呼叫系統 API？&lt;/h3>
&lt;p>Python 標準庫涵蓋了大多數常見需求，但有時我們需要：&lt;/p>
&lt;ul>
&lt;li>&lt;strong>存取特定系統功能&lt;/strong>：某些底層功能沒有 Python 封裝&lt;/li>
&lt;li>&lt;strong>避免 subprocess 開銷&lt;/strong>：執行外部命令有進程建立的成本&lt;/li>
&lt;li>&lt;strong>即時取得系統資訊&lt;/strong>：某些資訊需要直接從核心取得&lt;/li>
&lt;li>&lt;strong>與 C 函式庫互動&lt;/strong>：使用第三方 C 函式庫的功能&lt;/li>
&lt;/ul>
&lt;h3 id="常見場景">常見場景&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">需要直接呼叫系統 API 的情況：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">├── 取得主機名稱（gethostname）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">├── 取得使用者 ID（getuid, geteuid）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">├── 系統時間操作（time, gettimeofday）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">├── 檔案系統操作（sync, fsync）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">├── 記憶體資訊（sysinfo - Linux 限定）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">└── 其他未封裝的 POSIX/Windows API&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>雖然許多功能有 Python 對應（如 &lt;code>os.getpid()&lt;/code>、&lt;code>socket.gethostname()&lt;/code>），但理解如何直接呼叫系統 API 是重要的技能：&lt;/p>
&lt;ol>
&lt;li>學習 ctypes 的實際應用&lt;/li>
&lt;li>處理 Python 未封裝的功能&lt;/li>
&lt;li>理解 Python 標準庫的實作原理&lt;/li>
&lt;/ol>
&lt;h2 id="實作方案">實作方案&lt;/h2>
&lt;h3 id="基礎設置跨平台載入-libc">基礎設置：跨平台載入 libc&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># system_api.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="s2">使用 ctypes 呼叫系統 API 的範例模組。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="s2">跨平台支援 Linux、macOS 和 Windows。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes.util&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Optional&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">load_libc&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="s2"> 跨平台載入 C 函式庫。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="s2"> ctypes.CDLL: 載入的 C 函式庫物件
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="s2"> Raises:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="s2"> OSError: 無法載入 C 函式庫
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="c1"># Windows 使用 msvcrt&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;msvcrt&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="c1"># Unix-like 系統使用 find_library&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="n">libc_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">util&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">find_library&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;c&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">libc_name&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 嘗試常見路徑&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;darwin&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="n">libc_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;libc.dylib&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="n">libc_name&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s1">&amp;#39;libc.so.6&amp;#39;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">libc_name&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl">&lt;span class="c1"># 全域 libc 實例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl">&lt;span class="n">_libc&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Optional&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">None&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_libc&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">CDLL&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得 libc 的單例實例。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl"> &lt;span class="k">global&lt;/span> &lt;span class="n">_libc&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">_libc&lt;/span> &lt;span class="ow">is&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">44&lt;/span>&lt;span class="cl"> &lt;span class="n">_libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">load_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">45&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">_libc&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="範例-1取得主機名稱">範例 1：取得主機名稱&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">socket&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gethostname_ctypes&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 ctypes 呼叫 gethostname() 取得主機名稱。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2"> Args:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> max_len: 主機名稱緩衝區大小
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="s2"> 主機名稱字串
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="s2"> Raises:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="s2"> OSError: 系統呼叫失敗
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="c1"># int gethostname(char *name, size_t len)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_char_p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_size_t&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 建立緩衝區&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="n">buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_string_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 呼叫系統函式&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gethostname failed with code &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl">&lt;span class="c1"># 比較 ctypes 與 Python 標準庫&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ctypes gethostname: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">gethostname_ctypes&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;socket.gethostname: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">socket&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="範例-2取得-process-id">範例 2：取得 Process ID&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">getpid_ctypes&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 ctypes 呼叫 getpid() 取得當前 process ID。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> 當前 process 的 PID
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="c1"># pid_t getpid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getpid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getpid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getpid&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">getppid_ctypes&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 ctypes 呼叫 getppid() 取得父 process ID。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="s2"> 父 process 的 PID
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="c1"># pid_t getppid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getppid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getppid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getppid&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl">&lt;span class="c1"># 驗證結果&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ctypes getpid: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">getpid_ctypes&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;os.getpid: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getpid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ctypes getppid: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">getppid_ctypes&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;os.getppid: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getppid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="範例-3unix-時間戳記">範例 3：Unix 時間戳記&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span> &lt;span class="k">as&lt;/span> &lt;span class="nn">time_module&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">time_ctypes&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 ctypes 呼叫 time() 取得 Unix 時間戳記。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> 當前 Unix 時間戳記（秒）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="c1"># time_t time(time_t *tloc)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_void_p&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_long&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 傳入 NULL，直接取得回傳值&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kc">None&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="c1"># timeval 結構體（用於 gettimeofday）&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">Timeval&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">Structure&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="s2"> struct timeval {
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="s2"> time_t tv_sec; // 秒
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="s2"> suseconds_t tv_usec; // 微秒
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="s2"> };
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="n">_fields_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tv_sec&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_long&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;tv_usec&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_long&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gettimeofday_ctypes&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">tuple&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="nb">int&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">]:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 ctypes 呼叫 gettimeofday() 取得高精度時間。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl">&lt;span class="s2"> (秒, 微秒) 的 tuple
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">&lt;span class="s2"> Note:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl">&lt;span class="s2"> gettimeofday 在 POSIX.1-2008 中已標記為過時，
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl">&lt;span class="s2"> 建議使用 clock_gettime。此處僅作為教學範例。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">44&lt;/span>&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">45&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">46&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">NotImplementedError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;gettimeofday not available on Windows&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">47&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">48&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">49&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">50&lt;/span>&lt;span class="cl"> &lt;span class="c1"># int gettimeofday(struct timeval *tv, struct timezone *tz)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">51&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gettimeofday&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">52&lt;/span>&lt;span class="cl"> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">POINTER&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Timeval&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">53&lt;/span>&lt;span class="cl"> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_void_p&lt;/span> &lt;span class="c1"># timezone 已過時，傳 NULL&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">54&lt;/span>&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">55&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gettimeofday&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">56&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">57&lt;/span>&lt;span class="cl"> &lt;span class="n">tv&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">Timeval&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">58&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gettimeofday&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">byref&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">tv&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="kc">None&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">59&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">60&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">61&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gettimeofday failed with code &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">62&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">63&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">tv&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tv_sec&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">tv&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">tv_usec&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">64&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">65&lt;/span>&lt;span class="cl">&lt;span class="c1"># 驗證結果&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">66&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">67&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ctypes time: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">time_ctypes&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">68&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;time.time: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="nb">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">time_module&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">time&lt;/span>&lt;span class="p">())&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">69&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">70&lt;/span>&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">71&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">72&lt;/span>&lt;span class="cl"> &lt;span class="n">sec&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">usec&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">gettimeofday_ctypes&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">73&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gettimeofday: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">sec&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">.&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">usec&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">06d&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="範例-4使用者與群組-idunix-限定">範例 4：使用者與群組 ID（Unix 限定）&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">os&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_user_ids&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2"> 取得當前 process 的使用者和群組 ID。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> Returns:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2"> 包含 uid, euid, gid, egid 的字典
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="s2"> Note:
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="s2"> 僅支援 Unix-like 系統。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">NotImplementedError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;User IDs not applicable on Windows&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 設定函式簽名&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="c1"># uid_t getuid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getuid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getuid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_uint&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="c1"># uid_t geteuid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">geteuid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">geteuid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_uint&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="c1"># gid_t getgid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getgid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getgid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_uint&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl"> &lt;span class="c1"># gid_t getegid(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getegid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getegid&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_uint&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;uid&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getuid&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;euid&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">geteuid&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;gid&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getgid&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;egid&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getegid&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">44&lt;/span>&lt;span class="cl">&lt;span class="c1"># 驗證結果&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">45&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">46&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">47&lt;/span>&lt;span class="cl"> &lt;span class="n">ids&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_user_ids&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">48&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ctypes: uid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;uid&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, euid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;euid&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">49&lt;/span>&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;gid&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, egid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">ids&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;egid&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">50&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;os: uid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getuid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, euid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">geteuid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">51&lt;/span>&lt;span class="cl"> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getgid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">, egid=&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">os&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">getegid&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="跨平台考量">跨平台考量&lt;/h2>
&lt;h3 id="平台差異對照表">平台差異對照表&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>功能&lt;/th>
 &lt;th>Linux&lt;/th>
 &lt;th>macOS&lt;/th>
 &lt;th>Windows&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>libc 名稱&lt;/td>
 &lt;td>&lt;code>libc.so.6&lt;/code>&lt;/td>
 &lt;td>&lt;code>libc.dylib&lt;/code>&lt;/td>
 &lt;td>&lt;code>msvcrt&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>gethostname&lt;/code>&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>&lt;code>kernel32.GetComputerNameA&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>getpid&lt;/code>&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>&lt;code>kernel32.GetCurrentProcessId&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>time&lt;/code>&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>&lt;code>msvcrt.time&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;code>getuid/geteuid&lt;/code>&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>libc&lt;/td>
 &lt;td>不適用&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="windows-特定實作">Windows 特定實作&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">gethostname_windows&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> Windows 版本的 gethostname。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 kernel32.GetComputerNameA。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">NotImplementedError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;This function is Windows-only&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="n">kernel32&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">windll&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">kernel32&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="c1"># BOOL GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="n">buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_string_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="n">size&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_ulong&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">kernel32&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">GetComputerNameA&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">byref&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">size&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;GetComputerNameA failed&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">getpid_windows&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="s2"> Windows 版本的 getpid。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">&lt;span class="s2"> 使用 kernel32.GetCurrentProcessId。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">NotImplementedError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;This function is Windows-only&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="n">kernel32&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">windll&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">kernel32&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="c1"># DWORD GetCurrentProcessId(void)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="n">kernel32&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">GetCurrentProcessId&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="n">kernel32&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">GetCurrentProcessId&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_ulong&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">kernel32&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">GetCurrentProcessId&lt;/span>&lt;span class="p">()&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="跨平台封裝">跨平台封裝&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">sys&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_hostname&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;跨平台取得主機名稱。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">gethostname_windows&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">gethostname_ctypes&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_process_id&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;跨平台取得 process ID。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">sys&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">platform&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s1">&amp;#39;win32&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">getpid_windows&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">getpid_ctypes&lt;/span>&lt;span class="p">()&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="錯誤處理與安全性">錯誤處理與安全性&lt;/h2>
&lt;h3 id="常見錯誤類型">常見錯誤類型&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">errno&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">safe_gethostname&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">256&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> 安全版本的 gethostname，包含完整的錯誤處理。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 設定函式簽名&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_char_p&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_size_t&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 驗證參數&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">max_len&lt;/span> &lt;span class="o">&amp;lt;=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">ValueError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;max_len must be positive&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">max_len&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="mi">1024&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">ValueError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;max_len too large (max 1024)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 建立緩衝區&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="n">buffer&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">create_string_buffer&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 呼叫系統函式&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">buffer&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">max_len&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 取得錯誤碼&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="n">err&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get_errno&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">err&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ENAMETOOLONG&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ENAMETOOLONG&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;Hostname too long for buffer&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl"> &lt;span class="k">elif&lt;/span> &lt;span class="n">err&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EFAULT&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EFAULT&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;Invalid buffer address&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl"> &lt;span class="k">else&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">OSError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">err&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;gethostname failed: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">errorcode&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">get&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">err&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s1">&amp;#39;Unknown&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 解碼並處理可能的編碼錯誤&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl"> &lt;span class="k">try&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl"> &lt;span class="k">except&lt;/span> &lt;span class="ne">UnicodeDecodeError&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">buffer&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">value&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;latin-1&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="安全性考量">安全性考量&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="s2">使用 ctypes 時的安全性注意事項：
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="s2">1. 緩衝區溢位
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 永遠確保緩衝區大小足夠
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 使用 create_string_buffer() 而非直接操作指標
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="s2">2. 型別安全
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 務必設定 argtypes 和 restype
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 錯誤的型別可能導致程式崩潰或安全漏洞
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="s2">3. 記憶體管理
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="s2"> - ctypes 物件由 Python GC 管理
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 小心回呼函式的生命週期
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="s2">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="s2">4. 輸入驗證
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 永遠驗證使用者輸入
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="s2"> - 不要直接將未驗證的資料傳給 C 函式
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">&lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">secure_strlen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="s2"> 安全的 strlen 範例，包含輸入驗證。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">&lt;span class="s2"> &amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 輸入驗證&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="ow">not&lt;/span> &lt;span class="nb">isinstance&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">TypeError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Expected str, got {type(s).__name__}&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 限制長度避免 DoS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="n">MAX_LENGTH&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">10_000_000&lt;/span> &lt;span class="c1"># 10 MB&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="nb">len&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">MAX_LENGTH&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl"> &lt;span class="k">raise&lt;/span> &lt;span class="ne">ValueError&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;String too long (max &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">MAX_LENGTH&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> bytes)&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strlen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_char_p&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strlen&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_size_t&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 轉換為 bytes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="n">encoded&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">s&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">encode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strlen&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">encoded&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="錯誤碼處理">錯誤碼處理&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">errno&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">get_errno_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">err&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">str&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;取得錯誤碼對應的訊息。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">get_libc&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="c1"># char *strerror(int errnum)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strerror&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">argtypes&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_int&lt;/span>&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strerror&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">restype&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">ctypes&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">c_char_p&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">libc&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strerror&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">err&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">decode&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s1">&amp;#39;utf-8&amp;#39;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;Unknown error &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">err&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="c1"># 使用範例&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;ENOENT (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ENOENT&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">get_errno_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">ENOENT&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;EACCES (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EACCES&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">get_errno_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EACCES&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;EINVAL (&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EINVAL&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">): &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">get_errno_message&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">errno&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">EINVAL&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="效能比較ctypes-vs-subprocess">效能比較：ctypes vs subprocess&lt;/h2>
&lt;h3 id="測試腳本">測試腳本&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">subprocess&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">time&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="kn">import&lt;/span> &lt;span class="nn">statistics&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">typing&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Callable&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">benchmark&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">func&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">Callable&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">iterations&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">1000&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">-&amp;gt;&lt;/span> &lt;span class="nb">dict&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;&amp;#34;&amp;#34;執行效能測試並回傳統計資料。&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="n">times&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 暖機&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="n">func&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="c1"># 實際測試&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">_&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">iterations&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">perf_counter&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="n">func&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="n">end&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">time&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">perf_counter&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="n">times&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">append&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">end&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;mean&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">statistics&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">mean&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">times&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1_000_000&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="c1"># 轉換為微秒&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;stdev&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">statistics&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdev&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">times&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1_000_000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;min&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">min&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">times&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1_000_000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl"> &lt;span class="s1">&amp;#39;max&amp;#39;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="nb">max&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">times&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">1_000_000&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 1：ctypes&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">hostname_ctypes&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">gethostname_ctypes&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 2：subprocess&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">hostname_subprocess&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">subprocess&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">run&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;hostname&amp;#39;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl"> &lt;span class="n">capture_output&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="n">text&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="kc">True&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl"> &lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">stdout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">strip&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 3：Python 標準庫&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">42&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">hostname_stdlib&lt;/span>&lt;span class="p">():&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">43&lt;/span>&lt;span class="cl"> &lt;span class="kn">import&lt;/span> &lt;span class="nn">socket&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">44&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">socket&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="n">gethostname&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">45&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">46&lt;/span>&lt;span class="cl">&lt;span class="c1"># 執行測試&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">47&lt;/span>&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="vm">__name__&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="s2">&amp;#34;__main__&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">48&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;=&amp;#34;&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">60&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">49&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;取得主機名稱效能比較&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">50&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;=&amp;#34;&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">60&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">51&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">52&lt;/span>&lt;span class="cl"> &lt;span class="n">methods&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">53&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;ctypes&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">hostname_ctypes&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">54&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;subprocess&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">hostname_subprocess&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">55&lt;/span>&lt;span class="cl"> &lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;socket (stdlib)&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">hostname_stdlib&lt;/span>&lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">56&lt;/span>&lt;span class="cl"> &lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">57&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">58&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">func&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="n">methods&lt;/span>&lt;span class="p">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">59&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">benchmark&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">func&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">60&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">\n&lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2">:&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">61&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; 平均: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;mean&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> us&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">62&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; 標準差: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;stdev&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> us&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">63&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; 最小: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;min&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> us&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">64&lt;/span>&lt;span class="cl"> &lt;span class="nb">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="sa">f&lt;/span>&lt;span class="s2">&amp;#34; 最大: &lt;/span>&lt;span class="si">{&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="s1">&amp;#39;max&amp;#39;&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="si">:&lt;/span>&lt;span class="s2">.2f&lt;/span>&lt;span class="si">}&lt;/span>&lt;span class="s2"> us&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="效能測試結果">效能測試結果&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">============================================================
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">取得主機名稱效能比較
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">============================================================
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">ctypes:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> 平均: 1.52 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> 標準差: 0.31 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> 最小: 1.21 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> 最大: 8.45 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">subprocess:
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> 平均: 4523.67 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> 標準差: 892.34 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> 最小: 3128.45 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> 最大: 12456.78 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">socket (stdlib):
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> 平均: 0.89 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> 標準差: 0.18 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> 最小: 0.72 us
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl"> 最大: 4.23 us&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="結果分析">結果分析&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>方法&lt;/th>
 &lt;th>平均時間&lt;/th>
 &lt;th>相對 ctypes&lt;/th>
 &lt;th>適用場景&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;strong>socket (stdlib)&lt;/strong>&lt;/td>
 &lt;td>~0.9 us&lt;/td>
 &lt;td>0.6x (最快)&lt;/td>
 &lt;td>首選，已有封裝&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>ctypes&lt;/strong>&lt;/td>
 &lt;td>~1.5 us&lt;/td>
 &lt;td>1x (基準)&lt;/td>
 &lt;td>無標準庫支援時&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;strong>subprocess&lt;/strong>&lt;/td>
 &lt;td>~4500 us&lt;/td>
 &lt;td>~3000x (最慢)&lt;/td>
 &lt;td>需要執行外部命令時&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;strong>結論&lt;/strong>：&lt;/p></description><content:encoded><![CDATA[<p>本案例展示如何使用 ctypes 直接呼叫系統 API，處理 Python 標準庫未提供的底層功能。</p>
<h2 id="先備知識">先備知識</h2>
<ul>
<li><a href="/blog/python-advanced/05-c-extensions/ctypes-cffi/" data-link-title="4.1 ctypes 與 cffi：動態綁定" data-link-desc="使用 ctypes 和 cffi 呼叫 C 函式庫">4.1 ctypes 與 cffi：動態綁定</a></li>
<li><a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python</a></li>
</ul>
<h2 id="問題背景">問題背景</h2>
<h3 id="為什麼需要直接呼叫系統-api">為什麼需要直接呼叫系統 API？</h3>
<p>Python 標準庫涵蓋了大多數常見需求，但有時我們需要：</p>
<ul>
<li><strong>存取特定系統功能</strong>：某些底層功能沒有 Python 封裝</li>
<li><strong>避免 subprocess 開銷</strong>：執行外部命令有進程建立的成本</li>
<li><strong>即時取得系統資訊</strong>：某些資訊需要直接從核心取得</li>
<li><strong>與 C 函式庫互動</strong>：使用第三方 C 函式庫的功能</li>
</ul>
<h3 id="常見場景">常見場景</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">需要直接呼叫系統 API 的情況：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── 取得主機名稱（gethostname）
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── 取得使用者 ID（getuid, geteuid）
</span></span><span class="line"><span class="ln">4</span><span class="cl">├── 系統時間操作（time, gettimeofday）
</span></span><span class="line"><span class="ln">5</span><span class="cl">├── 檔案系統操作（sync, fsync）
</span></span><span class="line"><span class="ln">6</span><span class="cl">├── 記憶體資訊（sysinfo - Linux 限定）
</span></span><span class="line"><span class="ln">7</span><span class="cl">└── 其他未封裝的 POSIX/Windows API</span></span></code></pre></div><p>雖然許多功能有 Python 對應（如 <code>os.getpid()</code>、<code>socket.gethostname()</code>），但理解如何直接呼叫系統 API 是重要的技能：</p>
<ol>
<li>學習 ctypes 的實際應用</li>
<li>處理 Python 未封裝的功能</li>
<li>理解 Python 標準庫的實作原理</li>
</ol>
<h2 id="實作方案">實作方案</h2>
<h3 id="基礎設置跨平台載入-libc">基礎設置：跨平台載入 libc</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># system_api.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="s2">使用 ctypes 呼叫系統 API 的範例模組。
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s2">跨平台支援 Linux、macOS 和 Windows。
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes.util</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Optional</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="k">def</span> <span class="nf">load_libc</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">    跨平台載入 C 函式庫。
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="s2">        ctypes.CDLL: 載入的 C 函式庫物件
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="s2">    Raises:
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="s2">        OSError: 無法載入 C 函式庫
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="c1"># Windows 使用 msvcrt</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="k">return</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="s1">&#39;msvcrt&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="c1"># Unix-like 系統使用 find_library</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="n">libc_name</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">util</span><span class="o">.</span><span class="n">find_library</span><span class="p">(</span><span class="s1">&#39;c&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="k">if</span> <span class="n">libc_name</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">            <span class="c1"># 嘗試常見路徑</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">            <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;darwin&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">                <span class="n">libc_name</span> <span class="o">=</span> <span class="s1">&#39;libc.dylib&#39;</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">            <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">                <span class="n">libc_name</span> <span class="o">=</span> <span class="s1">&#39;libc.so.6&#39;</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">        <span class="k">return</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="n">libc_name</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="c1"># 全域 libc 實例</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="n">_libc</span><span class="p">:</span> <span class="n">Optional</span><span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">]</span> <span class="o">=</span> <span class="kc">None</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">
</span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="k">def</span> <span class="nf">get_libc</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">    <span class="s2">&#34;&#34;&#34;取得 libc 的單例實例。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">    <span class="k">global</span> <span class="n">_libc</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">    <span class="k">if</span> <span class="n">_libc</span> <span class="ow">is</span> <span class="kc">None</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">        <span class="n">_libc</span> <span class="o">=</span> <span class="n">load_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">    <span class="k">return</span> <span class="n">_libc</span></span></span></code></pre></div><h3 id="範例-1取得主機名稱">範例 1：取得主機名稱</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">socket</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">gethostname_ctypes</span><span class="p">(</span><span class="n">max_len</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">256</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    使用 ctypes 呼叫 gethostname() 取得主機名稱。
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">    Args:
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">        max_len: 主機名稱緩衝區大小
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">        主機名稱字串
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">    Raises:
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">        OSError: 系統呼叫失敗
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="c1"># int gethostname(char *name, size_t len)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_size_t</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="c1"># 建立緩衝區</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="n">buffer</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">create_string_buffer</span><span class="p">(</span><span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="c1"># 呼叫系統函式</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="k">if</span> <span class="n">result</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;gethostname failed with code </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="k">return</span> <span class="n">buffer</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">
</span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="c1"># 比較 ctypes 與 Python 標準庫</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ctypes gethostname: </span><span class="si">{</span><span class="n">gethostname_ctypes</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;socket.gethostname: </span><span class="si">{</span><span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="範例-2取得-process-id">範例 2：取得 Process ID</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">getpid_ctypes</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    使用 ctypes 呼叫 getpid() 取得當前 process ID。
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">        當前 process 的 PID
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="c1"># pid_t getpid(void)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getpid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getpid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">return</span> <span class="n">libc</span><span class="o">.</span><span class="n">getpid</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="k">def</span> <span class="nf">getppid_ctypes</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="s2">    使用 ctypes 呼叫 getppid() 取得父 process ID。
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="s2">        父 process 的 PID
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="c1"># pid_t getppid(void)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getppid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getppid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="k">return</span> <span class="n">libc</span><span class="o">.</span><span class="n">getppid</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">
</span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="c1"># 驗證結果</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ctypes getpid: </span><span class="si">{</span><span class="n">getpid_ctypes</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;os.getpid: </span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">getpid</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ctypes getppid: </span><span class="si">{</span><span class="n">getppid_ctypes</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;os.getppid: </span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">getppid</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="範例-3unix-時間戳記">範例 3：Unix 時間戳記</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span> <span class="k">as</span> <span class="nn">time_module</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">time_ctypes</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    使用 ctypes 呼叫 time() 取得 Unix 時間戳記。
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">        當前 Unix 時間戳記（秒）
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="c1"># time_t time(time_t *tloc)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_void_p</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">time</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_long</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="c1"># 傳入 NULL，直接取得回傳值</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">return</span> <span class="n">libc</span><span class="o">.</span><span class="n">time</span><span class="p">(</span><span class="kc">None</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c1"># timeval 結構體（用於 gettimeofday）</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="k">class</span> <span class="nc">Timeval</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">Structure</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="s2">    struct timeval {
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="s2">        time_t      tv_sec;   // 秒
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="s2">        suseconds_t tv_usec;  // 微秒
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="s2">    };
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="n">_fields_</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;tv_sec&#34;</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_long</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;tv_usec&#34;</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_long</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="k">def</span> <span class="nf">gettimeofday_ctypes</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">tuple</span><span class="p">[</span><span class="nb">int</span><span class="p">,</span> <span class="nb">int</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">35</span><span class="cl"><span class="s2">    使用 ctypes 呼叫 gettimeofday() 取得高精度時間。
</span></span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">37</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="s2">        (秒, 微秒) 的 tuple
</span></span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="s2">    Note:
</span></span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="s2">        gettimeofday 在 POSIX.1-2008 中已標記為過時，
</span></span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="s2">        建議使用 clock_gettime。此處僅作為教學範例。
</span></span></span><span class="line"><span class="ln">43</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">    <span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">&#34;gettimeofday not available on Windows&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">
</span></span><span class="line"><span class="ln">48</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">
</span></span><span class="line"><span class="ln">50</span><span class="cl">    <span class="c1"># int gettimeofday(struct timeval *tv, struct timezone *tz)</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gettimeofday</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">52</span><span class="cl">        <span class="n">ctypes</span><span class="o">.</span><span class="n">POINTER</span><span class="p">(</span><span class="n">Timeval</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">53</span><span class="cl">        <span class="n">ctypes</span><span class="o">.</span><span class="n">c_void_p</span>  <span class="c1"># timezone 已過時，傳 NULL</span>
</span></span><span class="line"><span class="ln">54</span><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="ln">55</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gettimeofday</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl">
</span></span><span class="line"><span class="ln">57</span><span class="cl">    <span class="n">tv</span> <span class="o">=</span> <span class="n">Timeval</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">58</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">gettimeofday</span><span class="p">(</span><span class="n">ctypes</span><span class="o">.</span><span class="n">byref</span><span class="p">(</span><span class="n">tv</span><span class="p">),</span> <span class="kc">None</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">59</span><span class="cl">
</span></span><span class="line"><span class="ln">60</span><span class="cl">    <span class="k">if</span> <span class="n">result</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">61</span><span class="cl">        <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;gettimeofday failed with code </span><span class="si">{</span><span class="n">result</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">62</span><span class="cl">
</span></span><span class="line"><span class="ln">63</span><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">tv</span><span class="o">.</span><span class="n">tv_sec</span><span class="p">,</span> <span class="n">tv</span><span class="o">.</span><span class="n">tv_usec</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">64</span><span class="cl">
</span></span><span class="line"><span class="ln">65</span><span class="cl"><span class="c1"># 驗證結果</span>
</span></span><span class="line"><span class="ln">66</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">67</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ctypes time: </span><span class="si">{</span><span class="n">time_ctypes</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">68</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;time.time: </span><span class="si">{</span><span class="nb">int</span><span class="p">(</span><span class="n">time_module</span><span class="o">.</span><span class="n">time</span><span class="p">())</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">69</span><span class="cl">
</span></span><span class="line"><span class="ln">70</span><span class="cl">    <span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln">71</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">!=</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">72</span><span class="cl">        <span class="n">sec</span><span class="p">,</span> <span class="n">usec</span> <span class="o">=</span> <span class="n">gettimeofday_ctypes</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">73</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;gettimeofday: </span><span class="si">{</span><span class="n">sec</span><span class="si">}</span><span class="s2">.</span><span class="si">{</span><span class="n">usec</span><span class="si">:</span><span class="s2">06d</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="範例-4使用者與群組-idunix-限定">範例 4：使用者與群組 ID（Unix 限定）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">os</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">def</span> <span class="nf">get_user_ids</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">    取得當前 process 的使用者和群組 ID。
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">    Returns:
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">        包含 uid, euid, gid, egid 的字典
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">    Note:
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">        僅支援 Unix-like 系統。
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">&#34;User IDs not applicable on Windows&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="c1"># 設定函式簽名</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="c1"># uid_t getuid(void)</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getuid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getuid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_uint</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="c1"># uid_t geteuid(void)</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">geteuid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">geteuid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_uint</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="c1"># gid_t getgid(void)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getgid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getgid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_uint</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="c1"># gid_t getegid(void)</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getegid</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getegid</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_uint</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">        <span class="s1">&#39;uid&#39;</span><span class="p">:</span> <span class="n">libc</span><span class="o">.</span><span class="n">getuid</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">        <span class="s1">&#39;euid&#39;</span><span class="p">:</span> <span class="n">libc</span><span class="o">.</span><span class="n">geteuid</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">        <span class="s1">&#39;gid&#39;</span><span class="p">:</span> <span class="n">libc</span><span class="o">.</span><span class="n">getgid</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">        <span class="s1">&#39;egid&#39;</span><span class="p">:</span> <span class="n">libc</span><span class="o">.</span><span class="n">getegid</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">
</span></span><span class="line"><span class="ln">44</span><span class="cl"><span class="c1"># 驗證結果</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">!=</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">        <span class="n">ids</span> <span class="o">=</span> <span class="n">get_user_ids</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ctypes: uid=</span><span class="si">{</span><span class="n">ids</span><span class="p">[</span><span class="s1">&#39;uid&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">, euid=</span><span class="si">{</span><span class="n">ids</span><span class="p">[</span><span class="s1">&#39;euid&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">, &#34;</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">              <span class="sa">f</span><span class="s2">&#34;gid=</span><span class="si">{</span><span class="n">ids</span><span class="p">[</span><span class="s1">&#39;gid&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">, egid=</span><span class="si">{</span><span class="n">ids</span><span class="p">[</span><span class="s1">&#39;egid&#39;</span><span class="p">]</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;os: uid=</span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">getuid</span><span class="p">()</span><span class="si">}</span><span class="s2">, euid=</span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">geteuid</span><span class="p">()</span><span class="si">}</span><span class="s2">, &#34;</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">              <span class="sa">f</span><span class="s2">&#34;gid=</span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">getgid</span><span class="p">()</span><span class="si">}</span><span class="s2">, egid=</span><span class="si">{</span><span class="n">os</span><span class="o">.</span><span class="n">getegid</span><span class="p">()</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h2 id="跨平台考量">跨平台考量</h2>
<h3 id="平台差異對照表">平台差異對照表</h3>
<table>
  <thead>
      <tr>
          <th>功能</th>
          <th>Linux</th>
          <th>macOS</th>
          <th>Windows</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>libc 名稱</td>
          <td><code>libc.so.6</code></td>
          <td><code>libc.dylib</code></td>
          <td><code>msvcrt</code></td>
      </tr>
      <tr>
          <td><code>gethostname</code></td>
          <td>libc</td>
          <td>libc</td>
          <td><code>kernel32.GetComputerNameA</code></td>
      </tr>
      <tr>
          <td><code>getpid</code></td>
          <td>libc</td>
          <td>libc</td>
          <td><code>kernel32.GetCurrentProcessId</code></td>
      </tr>
      <tr>
          <td><code>time</code></td>
          <td>libc</td>
          <td>libc</td>
          <td><code>msvcrt.time</code></td>
      </tr>
      <tr>
          <td><code>getuid/geteuid</code></td>
          <td>libc</td>
          <td>libc</td>
          <td>不適用</td>
      </tr>
  </tbody>
</table>
<h3 id="windows-特定實作">Windows 特定實作</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">gethostname_windows</span><span class="p">(</span><span class="n">max_len</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">256</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    Windows 版本的 gethostname。
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">    使用 kernel32.GetComputerNameA。
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">!=</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">&#34;This function is Windows-only&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="n">kernel32</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="c1"># BOOL GetComputerNameA(LPSTR lpBuffer, LPDWORD nSize)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="n">buffer</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">create_string_buffer</span><span class="p">(</span><span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="n">size</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_ulong</span><span class="p">(</span><span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">kernel32</span><span class="o">.</span><span class="n">GetComputerNameA</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">byref</span><span class="p">(</span><span class="n">size</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">result</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;GetComputerNameA failed&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="k">return</span> <span class="n">buffer</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="k">def</span> <span class="nf">getpid_windows</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="s2">    Windows 版本的 getpid。
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="s2">    使用 kernel32.GetCurrentProcessId。
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">!=</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">        <span class="k">raise</span> <span class="ne">NotImplementedError</span><span class="p">(</span><span class="s2">&#34;This function is Windows-only&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="n">kernel32</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">windll</span><span class="o">.</span><span class="n">kernel32</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="c1"># DWORD GetCurrentProcessId(void)</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="n">kernel32</span><span class="o">.</span><span class="n">GetCurrentProcessId</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="n">kernel32</span><span class="o">.</span><span class="n">GetCurrentProcessId</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_ulong</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">
</span></span><span class="line"><span class="ln">41</span><span class="cl">    <span class="k">return</span> <span class="n">kernel32</span><span class="o">.</span><span class="n">GetCurrentProcessId</span><span class="p">()</span></span></span></code></pre></div><h3 id="跨平台封裝">跨平台封裝</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">sys</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">def</span> <span class="nf">get_hostname</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="s2">&#34;&#34;&#34;跨平台取得主機名稱。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">        <span class="k">return</span> <span class="n">gethostname_windows</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="k">return</span> <span class="n">gethostname_ctypes</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="k">def</span> <span class="nf">get_process_id</span><span class="p">()</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="s2">&#34;&#34;&#34;跨平台取得 process ID。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">if</span> <span class="n">sys</span><span class="o">.</span><span class="n">platform</span> <span class="o">==</span> <span class="s1">&#39;win32&#39;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="k">return</span> <span class="n">getpid_windows</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="k">return</span> <span class="n">getpid_ctypes</span><span class="p">()</span></span></span></code></pre></div><h2 id="錯誤處理與安全性">錯誤處理與安全性</h2>
<h3 id="常見錯誤類型">常見錯誤類型</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">errno</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">safe_gethostname</span><span class="p">(</span><span class="n">max_len</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">256</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">    安全版本的 gethostname，包含完整的錯誤處理。
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="c1"># 設定函式簽名</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">,</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_size_t</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="c1"># 驗證參數</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">if</span> <span class="n">max_len</span> <span class="o">&lt;=</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&#34;max_len must be positive&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">if</span> <span class="n">max_len</span> <span class="o">&gt;</span> <span class="mi">1024</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s2">&#34;max_len too large (max 1024)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="c1"># 建立緩衝區</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="n">buffer</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">create_string_buffer</span><span class="p">(</span><span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="c1"># 呼叫系統函式</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">gethostname</span><span class="p">(</span><span class="n">buffer</span><span class="p">,</span> <span class="n">max_len</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="k">if</span> <span class="n">result</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="c1"># 取得錯誤碼</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="n">err</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">get_errno</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="k">if</span> <span class="n">err</span> <span class="o">==</span> <span class="n">errno</span><span class="o">.</span><span class="n">ENAMETOOLONG</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">            <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="n">errno</span><span class="o">.</span><span class="n">ENAMETOOLONG</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">                         <span class="s2">&#34;Hostname too long for buffer&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">        <span class="k">elif</span> <span class="n">err</span> <span class="o">==</span> <span class="n">errno</span><span class="o">.</span><span class="n">EFAULT</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">            <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="n">errno</span><span class="o">.</span><span class="n">EFAULT</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">                         <span class="s2">&#34;Invalid buffer address&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">        <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">            <span class="k">raise</span> <span class="ne">OSError</span><span class="p">(</span><span class="n">err</span><span class="p">,</span> <span class="sa">f</span><span class="s2">&#34;gethostname failed: </span><span class="si">{</span><span class="n">errno</span><span class="o">.</span><span class="n">errorcode</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">err</span><span class="p">,</span> <span class="s1">&#39;Unknown&#39;</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="c1"># 解碼並處理可能的編碼錯誤</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">    <span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">        <span class="k">return</span> <span class="n">buffer</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">    <span class="k">except</span> <span class="ne">UnicodeDecodeError</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">        <span class="k">return</span> <span class="n">buffer</span><span class="o">.</span><span class="n">value</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;latin-1&#39;</span><span class="p">)</span></span></span></code></pre></div><h3 id="安全性考量">安全性考量</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="s2">使用 ctypes 時的安全性注意事項：
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="s2">1. 緩衝區溢位
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s2">   - 永遠確保緩衝區大小足夠
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">   - 使用 create_string_buffer() 而非直接操作指標
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">2. 型別安全
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">   - 務必設定 argtypes 和 restype
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">   - 錯誤的型別可能導致程式崩潰或安全漏洞
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">3. 記憶體管理
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">   - ctypes 物件由 Python GC 管理
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">   - 小心回呼函式的生命週期
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">4. 輸入驗證
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s2">   - 永遠驗證使用者輸入
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="s2">   - 不要直接將未驗證的資料傳給 C 函式
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="k">def</span> <span class="nf">secure_strlen</span><span class="p">(</span><span class="n">s</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="s2">    安全的 strlen 範例，包含輸入驗證。
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="s2">    &#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="c1"># 輸入驗證</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">s</span><span class="p">,</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="k">raise</span> <span class="ne">TypeError</span><span class="p">(</span><span class="s2">&#34;Expected str, got {type(s).__name__}&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="c1"># 限制長度避免 DoS</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="n">MAX_LENGTH</span> <span class="o">=</span> <span class="mi">10_000_000</span>  <span class="c1"># 10 MB</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o">&gt;</span> <span class="n">MAX_LENGTH</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;String too long (max </span><span class="si">{</span><span class="n">MAX_LENGTH</span><span class="si">}</span><span class="s2"> bytes)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_size_t</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="c1"># 轉換為 bytes</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="n">encoded</span> <span class="o">=</span> <span class="n">s</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">
</span></span><span class="line"><span class="ln">41</span><span class="cl">    <span class="k">return</span> <span class="n">libc</span><span class="o">.</span><span class="n">strlen</span><span class="p">(</span><span class="n">encoded</span><span class="p">)</span></span></span></code></pre></div><h3 id="錯誤碼處理">錯誤碼處理</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">errno</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">def</span> <span class="nf">get_errno_message</span><span class="p">(</span><span class="n">err</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="s2">&#34;&#34;&#34;取得錯誤碼對應的訊息。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="c1"># char *strerror(int errnum)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">strerror</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_int</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">strerror</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">strerror</span><span class="p">(</span><span class="n">err</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="k">if</span> <span class="n">result</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="k">return</span> <span class="n">result</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">return</span> <span class="sa">f</span><span class="s2">&#34;Unknown error </span><span class="si">{</span><span class="n">err</span><span class="si">}</span><span class="s2">&#34;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"># 使用範例</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;ENOENT (</span><span class="si">{</span><span class="n">errno</span><span class="o">.</span><span class="n">ENOENT</span><span class="si">}</span><span class="s2">): </span><span class="si">{</span><span class="n">get_errno_message</span><span class="p">(</span><span class="n">errno</span><span class="o">.</span><span class="n">ENOENT</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;EACCES (</span><span class="si">{</span><span class="n">errno</span><span class="o">.</span><span class="n">EACCES</span><span class="si">}</span><span class="s2">): </span><span class="si">{</span><span class="n">get_errno_message</span><span class="p">(</span><span class="n">errno</span><span class="o">.</span><span class="n">EACCES</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;EINVAL (</span><span class="si">{</span><span class="n">errno</span><span class="o">.</span><span class="n">EINVAL</span><span class="si">}</span><span class="s2">): </span><span class="si">{</span><span class="n">get_errno_message</span><span class="p">(</span><span class="n">errno</span><span class="o">.</span><span class="n">EINVAL</span><span class="p">)</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span></span></span></code></pre></div><h2 id="效能比較ctypes-vs-subprocess">效能比較：ctypes vs subprocess</h2>
<h3 id="測試腳本">測試腳本</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">subprocess</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span> <span class="nn">statistics</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Callable</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">def</span> <span class="nf">benchmark</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="n">Callable</span><span class="p">,</span> <span class="n">iterations</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="s2">&#34;&#34;&#34;執行效能測試並回傳統計資料。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">times</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="c1"># 暖機</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="n">func</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="c1"># 實際測試</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">iterations</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="n">func</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="n">times</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="s1">&#39;mean&#39;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1_000_000</span><span class="p">,</span>  <span class="c1"># 轉換為微秒</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="s1">&#39;stdev&#39;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">stdev</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1_000_000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="s1">&#39;min&#39;</span><span class="p">:</span> <span class="nb">min</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1_000_000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="s1">&#39;max&#39;</span><span class="p">:</span> <span class="nb">max</span><span class="p">(</span><span class="n">times</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1_000_000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="c1"># 方法 1：ctypes</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="k">def</span> <span class="nf">hostname_ctypes</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="k">return</span> <span class="n">gethostname_ctypes</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="c1"># 方法 2：subprocess</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="k">def</span> <span class="nf">hostname_subprocess</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">run</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">        <span class="p">[</span><span class="s1">&#39;hostname&#39;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">        <span class="n">capture_output</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="n">text</span><span class="o">=</span><span class="kc">True</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="o">.</span><span class="n">stdout</span><span class="o">.</span><span class="n">strip</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">
</span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="c1"># 方法 3：Python 標準庫</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl"><span class="k">def</span> <span class="nf">hostname_stdlib</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">    <span class="kn">import</span> <span class="nn">socket</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">    <span class="k">return</span> <span class="n">socket</span><span class="o">.</span><span class="n">gethostname</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">
</span></span><span class="line"><span class="ln">46</span><span class="cl"><span class="c1"># 執行測試</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">60</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;取得主機名稱效能比較&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">60</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">
</span></span><span class="line"><span class="ln">52</span><span class="cl">    <span class="n">methods</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">53</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;ctypes&#34;</span><span class="p">,</span> <span class="n">hostname_ctypes</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">54</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;subprocess&#34;</span><span class="p">,</span> <span class="n">hostname_subprocess</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">55</span><span class="cl">        <span class="p">(</span><span class="s2">&#34;socket (stdlib)&#34;</span><span class="p">,</span> <span class="n">hostname_stdlib</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl">    <span class="p">]</span>
</span></span><span class="line"><span class="ln">57</span><span class="cl">
</span></span><span class="line"><span class="ln">58</span><span class="cl">    <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">func</span> <span class="ow">in</span> <span class="n">methods</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">59</span><span class="cl">        <span class="n">result</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">60</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="se">\n</span><span class="si">{</span><span class="n">name</span><span class="si">}</span><span class="s2">:&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">61</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  平均: </span><span class="si">{</span><span class="n">result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> us&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">62</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  標準差: </span><span class="si">{</span><span class="n">result</span><span class="p">[</span><span class="s1">&#39;stdev&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> us&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">63</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  最小: </span><span class="si">{</span><span class="n">result</span><span class="p">[</span><span class="s1">&#39;min&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> us&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">64</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  最大: </span><span class="si">{</span><span class="n">result</span><span class="p">[</span><span class="s1">&#39;max&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2"> us&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="效能測試結果">效能測試結果</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">============================================================
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">取得主機名稱效能比較
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">============================================================
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">ctypes:
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">  平均: 1.52 us
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">  標準差: 0.31 us
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  最小: 1.21 us
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  最大: 8.45 us
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">subprocess:
</span></span><span class="line"><span class="ln">12</span><span class="cl">  平均: 4523.67 us
</span></span><span class="line"><span class="ln">13</span><span class="cl">  標準差: 892.34 us
</span></span><span class="line"><span class="ln">14</span><span class="cl">  最小: 3128.45 us
</span></span><span class="line"><span class="ln">15</span><span class="cl">  最大: 12456.78 us
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">socket (stdlib):
</span></span><span class="line"><span class="ln">18</span><span class="cl">  平均: 0.89 us
</span></span><span class="line"><span class="ln">19</span><span class="cl">  標準差: 0.18 us
</span></span><span class="line"><span class="ln">20</span><span class="cl">  最小: 0.72 us
</span></span><span class="line"><span class="ln">21</span><span class="cl">  最大: 4.23 us</span></span></code></pre></div><h3 id="結果分析">結果分析</h3>
<table>
  <thead>
      <tr>
          <th>方法</th>
          <th>平均時間</th>
          <th>相對 ctypes</th>
          <th>適用場景</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>socket (stdlib)</strong></td>
          <td>~0.9 us</td>
          <td>0.6x (最快)</td>
          <td>首選，已有封裝</td>
      </tr>
      <tr>
          <td><strong>ctypes</strong></td>
          <td>~1.5 us</td>
          <td>1x (基準)</td>
          <td>無標準庫支援時</td>
      </tr>
      <tr>
          <td><strong>subprocess</strong></td>
          <td>~4500 us</td>
          <td>~3000x (最慢)</td>
          <td>需要執行外部命令時</td>
      </tr>
  </tbody>
</table>
<p><strong>結論</strong>：</p>
<ol>
<li><strong>優先使用標準庫</strong>：如果 Python 標準庫有對應功能，通常是最佳選擇</li>
<li><strong>ctypes 是好的替代方案</strong>：效能接近標準庫，適合未封裝的系統 API</li>
<li><strong>避免 subprocess 取得簡單資訊</strong>：進程建立開銷約 3000 倍</li>
</ol>
<h2 id="設計權衡">設計權衡</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>ctypes</th>
          <th>subprocess</th>
          <th>標準庫</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>效能</strong></td>
          <td>優秀 (~1-5 us)</td>
          <td>差 (~3-5 ms)</td>
          <td>最佳 (~1 us)</td>
      </tr>
      <tr>
          <td><strong>可移植性</strong></td>
          <td>需處理平台差異</td>
          <td>取決於命令可用性</td>
          <td>優秀</td>
      </tr>
      <tr>
          <td><strong>複雜度</strong></td>
          <td>中（需了解 C 型別）</td>
          <td>低</td>
          <td>低</td>
      </tr>
      <tr>
          <td><strong>安全性</strong></td>
          <td>需謹慎處理</td>
          <td>需防止命令注入</td>
          <td>良好</td>
      </tr>
      <tr>
          <td><strong>功能範圍</strong></td>
          <td>廣（任何 C 函式）</td>
          <td>廣（任何命令）</td>
          <td>受限於已實作功能</td>
      </tr>
  </tbody>
</table>
<h2 id="實際應用建議">實際應用建議</h2>
<h3 id="何時使用-ctypes">何時使用 ctypes</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">適合使用 ctypes 的情況：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">├── Python 標準庫沒有對應功能
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├── 需要呼叫特定平台的 API
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── 效能是關鍵考量
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">├── 需要與 C 函式庫整合
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">└── 希望避免編譯步驟（相比 Cython）
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">不建議使用 ctypes 的情況：
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">├── 標準庫已有對應功能
</span></span><span class="line"><span class="ln">10</span><span class="cl">├── 大量複雜的 C 介面（考慮 cffi 或 Cython）
</span></span><span class="line"><span class="ln">11</span><span class="cl">├── 需要頻繁傳遞大量資料（考慮 NumPy）
</span></span><span class="line"><span class="ln">12</span><span class="cl">└── 團隊不熟悉 C 語言</span></span></code></pre></div><h3 id="最佳實踐">最佳實踐</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="s2">ctypes 呼叫系統 API 的最佳實踐：
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="s2">1. 封裝成模組
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="s2">   - 將 ctypes 呼叫封裝在獨立模組中
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="s2">   - 提供清晰的 Python API
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">2. 完整的型別宣告
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">   - 永遠設定 argtypes 和 restype
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">   - 使用適當的 ctypes 型別
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">3. 錯誤處理
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">   - 檢查回傳值
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">   - 處理 errno
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">   - 提供有意義的錯誤訊息
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s2">4. 跨平台支援
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="s2">   - 使用 ctypes.util.find_library()
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="s2">   - 提供平台特定的實作
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="s2">   - 考慮使用 Python 標準庫作為 fallback
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="s2">5. 文件與測試
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="s2">   - 記錄 C 函式的原型
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="s2">   - 與 Python 標準庫比較結果
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="s2">   - 包含效能測試
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span></span></span></code></pre></div><h2 id="練習">練習</h2>
<h3 id="基礎練習">基礎練習</h3>
<p>使用 ctypes 實作以下功能：</p>
<ol>
<li><strong>取得環境變數</strong>：呼叫 <code>getenv()</code> 函式</li>
<li><strong>設定環境變數</strong>：呼叫 <code>setenv()</code> 或 <code>putenv()</code> 函式（Unix）</li>
<li><strong>取得當前工作目錄</strong>：呼叫 <code>getcwd()</code> 函式</li>
</ol>
<p>提示：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># getenv 範例框架</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">def</span> <span class="nf">getenv_ctypes</span><span class="p">(</span><span class="n">name</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">Optional</span><span class="p">[</span><span class="nb">str</span><span class="p">]:</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="s2">&#34;&#34;&#34;使用 ctypes 取得環境變數。&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="n">libc</span> <span class="o">=</span> <span class="n">get_libc</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="c1"># char *getenv(const char *name)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getenv</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">libc</span><span class="o">.</span><span class="n">getenv</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">libc</span><span class="o">.</span><span class="n">getenv</span><span class="p">(</span><span class="n">name</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="c1"># 完成實作...</span></span></span></code></pre></div><h3 id="進階練習">進階練習</h3>
<ol>
<li>
<p>實作一個跨平台的系統資訊模組，包含：</p>
<ul>
<li>主機名稱</li>
<li>Process ID</li>
<li>使用者 ID（Unix）/ 使用者名稱（Windows）</li>
<li>系統時間</li>
</ul>
</li>
<li>
<p>比較你的實作與 <code>psutil</code> 套件的效能差異。</p>
</li>
</ol>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://docs.python.org/3/library/ctypes.html">Python ctypes 官方文件</a></li>
<li><a href="https://man7.org/linux/man-pages/dir_section_2.html">Linux man pages - section 2 (system calls)</a></li>
<li><a href="https://docs.microsoft.com/en-us/windows/win32/api/">Windows API Reference</a></li>
<li><a href="https://pubs.opengroup.org/onlinepubs/9699919799/">POSIX 標準</a></li>
</ul>
<hr>
<p><em>返回：<a href="/blog/python-advanced/05-c-extensions/case-studies/" data-link-title="案例研究" data-link-desc="基於 .claude/lib 實際程式碼的 C 擴展案例">案例研究</a></em>
<em>返回：<a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python</a></em></p>
]]></content:encoded></item><item><title>4.2 Cython：Python 語法的 C 速度</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/cython/</link><pubDate>Tue, 20 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/cython/</guid><description>&lt;p>本章介紹 Cython，一種 Python 的超集語言，可以編譯成 C 程式碼。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>理解 Cython 的編譯流程&lt;/li>
&lt;li>使用型別宣告加速程式碼&lt;/li>
&lt;li>使用 Cython 包裝 C 函式庫&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="原理層cython-是什麼">【原理層】Cython 是什麼？&lt;/h2>
&lt;h3 id="python-的超集">Python 的超集&lt;/h3>
&lt;p>Cython 是一種程式語言，它是 Python 的超集：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">合法的 Python 程式碼 → 合法的 Cython 程式碼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl"> → 但 Cython 可以加入更多語法
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">Cython 特有語法：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">- cdef：宣告 C 變數或函式
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">- cpdef：同時暴露給 Python 和 C
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">- cimport：匯入 .pxd 檔案
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">- nogil：標記不需要 GIL 的區塊&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="編譯流程">編譯流程&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">.pyx (Cython 原始碼)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> ↓ Cython 編譯器
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">.c (C 原始碼)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> ↓ C 編譯器 (gcc, clang, MSVC)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">.so / .pyd (Python 擴展模組)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> ↓ import
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">Python 程式&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="為什麼-cython-比-python-快">為什麼 Cython 比 Python 快？&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 純 Python：每次操作都是物件操作&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">python_sum&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> &lt;span class="n">total&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1"># 建立 int 物件&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span> &lt;span class="c1"># 建立 range 物件，迭代器&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="n">total&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="c1"># 呼叫 __add__，建立新物件&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">total&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="c1"># Cython：可以使用原生 C 型別&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">cython_sum&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">int&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="n">cdef&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="n">total&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span> &lt;span class="c1"># C 的 int，不是 Python 物件&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="n">cdef&lt;/span> &lt;span class="nb">int&lt;/span> &lt;span class="n">i&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span> &lt;span class="c1"># 編譯成 C 的 for 迴圈&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="n">total&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="c1"># 單一 CPU 指令&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">total&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>效能差異的來源：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>操作&lt;/th>
 &lt;th>Python&lt;/th>
 &lt;th>Cython (有型別)&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>變數存取&lt;/td>
 &lt;td>dict 查找&lt;/td>
 &lt;td>直接記憶體存取&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>整數加法&lt;/td>
 &lt;td>物件方法呼叫&lt;/td>
 &lt;td>CPU 指令&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>迴圈&lt;/td>
 &lt;td>迭代器協議&lt;/td>
 &lt;td>C for 迴圈&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>函式呼叫&lt;/td>
 &lt;td>建立 frame 物件&lt;/td>
 &lt;td>C 函式呼叫&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="設計層cython-基礎語法">【設計層】Cython 基礎語法&lt;/h2>
&lt;h3 id="安裝與設定">安裝與設定&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">pip install cython
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="c1"># 檢查版本&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">python -c &lt;span class="s2">&amp;#34;import cython; print(cython.__version__)&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="第一個-cython-模組">第一個 Cython 模組&lt;/h3>
&lt;p>建立 &lt;code>example.pyx&lt;/code>：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cython" data-lang="cython">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c"># example.pyx&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">say_hello&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">name&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> &lt;span class="sd">&amp;#34;&amp;#34;&amp;#34;純 Python 函式，也是合法的 Cython&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="k">print&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">f&lt;/span>&lt;span class="s">&amp;#34;Hello, {name}!&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="k">def&lt;/span> &lt;span class="nf">compute_sum&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">int&lt;/span> &lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="sd">&amp;#34;&amp;#34;&amp;#34;加入型別宣告的函式&amp;#34;&amp;#34;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="k">cdef&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="nf">i&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl"> &lt;span class="k">cdef&lt;/span> &lt;span class="kt">long&lt;/span> &lt;span class="nf">total&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">0&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="n">i&lt;/span> &lt;span class="ow">in&lt;/span> &lt;span class="nb">range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">n&lt;/span>&lt;span class="p">):&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="n">total&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">i&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">total&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>建立 &lt;code>setup.py&lt;/code>：&lt;/p></description><content:encoded><![CDATA[<p>本章介紹 Cython，一種 Python 的超集語言，可以編譯成 C 程式碼。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>理解 Cython 的編譯流程</li>
<li>使用型別宣告加速程式碼</li>
<li>使用 Cython 包裝 C 函式庫</li>
</ol>
<hr>
<h2 id="原理層cython-是什麼">【原理層】Cython 是什麼？</h2>
<h3 id="python-的超集">Python 的超集</h3>
<p>Cython 是一種程式語言，它是 Python 的超集：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">合法的 Python 程式碼 → 合法的 Cython 程式碼
</span></span><span class="line"><span class="ln">2</span><span class="cl">                    → 但 Cython 可以加入更多語法
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl">Cython 特有語法：
</span></span><span class="line"><span class="ln">5</span><span class="cl">- cdef：宣告 C 變數或函式
</span></span><span class="line"><span class="ln">6</span><span class="cl">- cpdef：同時暴露給 Python 和 C
</span></span><span class="line"><span class="ln">7</span><span class="cl">- cimport：匯入 .pxd 檔案
</span></span><span class="line"><span class="ln">8</span><span class="cl">- nogil：標記不需要 GIL 的區塊</span></span></code></pre></div><h3 id="編譯流程">編譯流程</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">.pyx (Cython 原始碼)
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">    │
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    ↓ Cython 編譯器
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">.c (C 原始碼)
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    │
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    ↓ C 編譯器 (gcc, clang, MSVC)
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">.so / .pyd (Python 擴展模組)
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    │
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    ↓ import
</span></span><span class="line"><span class="ln">10</span><span class="cl">Python 程式</span></span></code></pre></div><h3 id="為什麼-cython-比-python-快">為什麼 Cython 比 Python 快？</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 純 Python：每次操作都是物件操作</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">def</span> <span class="nf">python_sum</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>           <span class="c1"># 建立 int 物件</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>  <span class="c1"># 建立 range 物件，迭代器</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span>      <span class="c1"># 呼叫 __add__，建立新物件</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="k">return</span> <span class="n">total</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># Cython：可以使用原生 C 型別</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="k">def</span> <span class="nf">cython_sum</span><span class="p">(</span><span class="nb">int</span> <span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="n">cdef</span> <span class="nb">int</span> <span class="n">total</span> <span class="o">=</span> <span class="mi">0</span>  <span class="c1"># C 的 int，不是 Python 物件</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">cdef</span> <span class="nb">int</span> <span class="n">i</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>  <span class="c1"># 編譯成 C 的 for 迴圈</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span>      <span class="c1"># 單一 CPU 指令</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="k">return</span> <span class="n">total</span></span></span></code></pre></div><p>效能差異的來源：</p>
<table>
  <thead>
      <tr>
          <th>操作</th>
          <th>Python</th>
          <th>Cython (有型別)</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>變數存取</td>
          <td>dict 查找</td>
          <td>直接記憶體存取</td>
      </tr>
      <tr>
          <td>整數加法</td>
          <td>物件方法呼叫</td>
          <td>CPU 指令</td>
      </tr>
      <tr>
          <td>迴圈</td>
          <td>迭代器協議</td>
          <td>C for 迴圈</td>
      </tr>
      <tr>
          <td>函式呼叫</td>
          <td>建立 frame 物件</td>
          <td>C 函式呼叫</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="設計層cython-基礎語法">【設計層】Cython 基礎語法</h2>
<h3 id="安裝與設定">安裝與設定</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl">pip install cython
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="c1"># 檢查版本</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">python -c <span class="s2">&#34;import cython; print(cython.__version__)&#34;</span></span></span></code></pre></div><h3 id="第一個-cython-模組">第一個 Cython 模組</h3>
<p>建立 <code>example.pyx</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># example.pyx</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">def</span> <span class="nf">say_hello</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="sd">&#34;&#34;&#34;純 Python 函式，也是合法的 Cython&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="s">&#34;Hello, {name}!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="k">def</span> <span class="nf">compute_sum</span><span class="p">(</span><span class="nb">int</span> <span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="sd">&#34;&#34;&#34;加入型別宣告的函式&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">i</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">cdef</span> <span class="kt">long</span> <span class="nf">total</span> <span class="o">=</span> <span class="mf">0</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="n">total</span> <span class="o">+=</span> <span class="n">i</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">return</span> <span class="n">total</span></span></span></code></pre></div><p>建立 <code>setup.py</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># setup.py</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="kn">from</span> <span class="nn">setuptools</span> <span class="kn">import</span> <span class="n">setup</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="kn">from</span> <span class="nn">Cython.Build</span> <span class="kn">import</span> <span class="n">cythonize</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="n">setup</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">    <span class="n">ext_modules</span><span class="o">=</span><span class="n">cythonize</span><span class="p">(</span><span class="s2">&#34;example.pyx&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><p>編譯與使用：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 編譯</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">python setup.py build_ext --inplace
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 使用</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">python -c <span class="s2">&#34;import example; example.say_hello(&#39;Cython&#39;)&#34;</span></span></span></code></pre></div><h3 id="變數宣告">變數宣告</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># 型別宣告語法</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c"># cdef：宣告 C 變數（只在 Cython 內部可見）</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">cdef</span> <span class="kt">int</span> <span class="nf">x</span> <span class="o">=</span> <span class="mf">10</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">cdef</span> <span class="kt">double</span> <span class="nf">y</span> <span class="o">=</span> <span class="mf">3.14</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">cdef</span> <span class="kt">char</span>* <span class="nf">s</span> <span class="o">=</span> <span class="s">&#34;hello&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c"># 多個變數</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="nb">int</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">double</span> <span class="n">d</span> <span class="o">=</span> <span class="mf">0.0</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="nb">list</span> <span class="n">my_list</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c"># 型別推斷（Python 3 風格）</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="k">cdef</span> <span class="kt">int</span> <span class="nf">x</span> <span class="o">=</span> <span class="mf">10</span>      <span class="c"># 明確宣告</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="n">x</span><span class="p">:</span> <span class="n">cython</span><span class="o">.</span><span class="n">int</span> <span class="o">=</span> <span class="mf">10</span>   <span class="c"># 註解風格（Pure Python 模式）</span></span></span></code></pre></div><h3 id="函式類型">函式類型</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># def：Python 函式，可從 Python 呼叫</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">def</span> <span class="nf">python_func</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c"># cdef：C 函式，只能從 Cython 呼叫，最快</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">cdef</span> <span class="kt">int</span> <span class="nf">c_func</span><span class="p">(</span><span class="nb">int</span> <span class="n">x</span><span class="p">,</span> <span class="nb">int</span> <span class="n">y</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c"># cpdef：同時產生 Python 和 C 版本</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="k">cpdef</span> <span class="kt">int</span> <span class="nf">hybrid_func</span><span class="p">(</span><span class="nb">int</span> <span class="n">x</span><span class="p">,</span> <span class="nb">int</span> <span class="n">y</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c"># 使用情境</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="k">def</span> <span class="nf">api_func</span><span class="p">(</span><span class="nb">int</span> <span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="sd">&#34;&#34;&#34;公開 API&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">i</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">total</span> <span class="o">=</span> <span class="mf">0</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="n">total</span> <span class="o">=</span> <span class="n">_helper</span><span class="p">(</span><span class="n">total</span><span class="p">,</span> <span class="n">i</span><span class="p">)</span>  <span class="c"># 呼叫 cdef 函式</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="k">return</span> <span class="n">total</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="k">cdef</span> <span class="kt">int</span> <span class="nf">_helper</span><span class="p">(</span><span class="nb">int</span> <span class="n">a</span><span class="p">,</span> <span class="nb">int</span> <span class="n">b</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="sd">&#34;&#34;&#34;內部輔助函式，不暴露給 Python&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span></span></span></code></pre></div><h3 id="型別轉換">型別轉換</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># 隱式轉換</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">cdef</span> <span class="kt">int</span> <span class="nf">i</span> <span class="o">=</span> <span class="mf">10</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">cdef</span> <span class="kt">double</span> <span class="nf">d</span> <span class="o">=</span> <span class="n">i</span>  <span class="c"># int → double，自動轉換</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c"># 明確轉換</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">cdef</span> <span class="kt">double</span> <span class="nf">x</span> <span class="o">=</span> <span class="mf">3.14</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="k">cdef</span> <span class="kt">int</span> <span class="nf">y</span> <span class="o">=</span> <span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span><span class="n">x</span>  <span class="c"># 截斷為 3</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c"># Python 物件與 C 型別</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="k">def</span> <span class="nf">convert_example</span><span class="p">(</span><span class="n">obj</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">c_int</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="c"># Python int → C int</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="n">c_int</span> <span class="o">=</span> <span class="p">&lt;</span><span class="kt">int</span><span class="p">&gt;</span><span class="n">obj</span>  <span class="c"># 可能 overflow</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="c"># 安全轉換</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="nb">int</span><span class="p">)</span> <span class="ow">and</span> <span class="o">-</span><span class="mf">2147483648</span> <span class="o">&lt;=</span> <span class="n">obj</span> <span class="o">&lt;=</span> <span class="mf">2147483647</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">        <span class="n">c_int</span> <span class="o">=</span> <span class="n">obj</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="k">return</span> <span class="n">c_int</span></span></span></code></pre></div><hr>
<h2 id="實作層cython-優化技巧">【實作層】Cython 優化技巧</h2>
<h3 id="使用-cython--a-分析">使用 cython -a 分析</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 產生帶註解的 HTML 報告</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">cython -a example.pyx</span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">HTML 報告的顏色含義：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── 白色：純 C 程式碼，最快
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── 淺黃色：少量 Python API 呼叫
</span></span><span class="line"><span class="ln">4</span><span class="cl">├── 深黃色：較多 Python 互動
</span></span><span class="line"><span class="ln">5</span><span class="cl">└── 橙色/紅色：大量 Python 操作，需要優化</span></span></code></pre></div><h3 id="常見優化模式">常見優化模式</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># 優化前：大量黃色</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">def</span> <span class="nf">slow_function</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="n">total</span> <span class="o">=</span> <span class="mf">0</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">data</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="n">total</span> <span class="o">+=</span> <span class="n">item</span> <span class="o">*</span> <span class="n">item</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="k">return</span> <span class="n">total</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c"># 優化後：大部分白色</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="k">def</span> <span class="nf">fast_function</span><span class="p">(</span><span class="n">double</span><span class="p">[:]</span> <span class="n">data</span><span class="p">):</span>  <span class="c"># 型別化記憶體視圖</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">cdef</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="nb">int</span> <span class="n">i</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="nb">int</span> <span class="n">n</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="n">double</span> <span class="n">total</span> <span class="o">=</span> <span class="mf">0.0</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="n">total</span> <span class="o">+=</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">return</span> <span class="n">total</span></span></span></code></pre></div><h3 id="停用邊界檢查">停用邊界檢查</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># 預設：有邊界檢查（安全但較慢）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">cdef</span> <span class="kt">double</span>[<span class="p">:]</span> <span class="n">arr</span> <span class="o">=</span> <span class="n">some_array</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c"># 停用檢查（確定安全時使用）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">cimport</span> <span class="nn">cython</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="nd">@cython</span><span class="o">.</span><span class="n">boundscheck</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>  <span class="c"># 停用邊界檢查</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="nd">@cython</span><span class="o">.</span><span class="n">wraparound</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>   <span class="c"># 停用負數索引</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="k">def</span> <span class="nf">optimized_sum</span><span class="p">(</span><span class="n">double</span><span class="p">[:]</span> <span class="n">arr</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">i</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">n</span> <span class="o">=</span> <span class="n">arr</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">cdef</span> <span class="kt">double</span> <span class="nf">total</span> <span class="o">=</span> <span class="mf">0.0</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="n">total</span> <span class="o">+=</span> <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">return</span> <span class="n">total</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c"># 或者使用全域設定</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c"># cython: boundscheck=False</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c"># cython: wraparound=False</span></span></span></code></pre></div><h3 id="釋放-gil">釋放 GIL</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">from</span> <span class="nn">cython.parallel</span> <span class="k">import</span> <span class="n">prange</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c"># nogil：標記不需要 GIL 的區塊</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">cdef</span> <span class="kt">double</span> <span class="nf">compute_heavy</span><span class="p">(</span><span class="n">double</span> <span class="n">x</span><span class="p">)</span> <span class="k">nogil</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="sd">&#34;&#34;&#34;純 C 計算，不涉及 Python 物件&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="k">cdef</span> <span class="kt">double</span> <span class="nf">result</span> <span class="o">=</span> <span class="mf">0.0</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">i</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mf">1000</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="n">result</span> <span class="o">+=</span> <span class="n">x</span> <span class="o">*</span> <span class="n">i</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">return</span> <span class="n">result</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="k">def</span> <span class="nf">parallel_compute</span><span class="p">(</span><span class="n">double</span><span class="p">[:]</span> <span class="n">data</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">i</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">n</span> <span class="o">=</span> <span class="n">data</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">cdef</span> <span class="kt">double</span>[<span class="p">:]</span> <span class="n">results</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="c"># 使用 OpenMP 平行化</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">with</span> <span class="k">nogil</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">prange</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">            <span class="n">results</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">compute_heavy</span><span class="p">(</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">])</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">asarray</span><span class="p">(</span><span class="n">results</span><span class="p">)</span></span></span></code></pre></div><hr>
<h2 id="實作層與-numpy-整合">【實作層】與 NumPy 整合</h2>
<h3 id="記憶體視圖">記憶體視圖</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">cimport</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">cnp</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c"># 型別化記憶體視圖（推薦）</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">def</span> <span class="nf">process_array</span><span class="p">(</span><span class="n">double</span><span class="p">[:,</span> <span class="p">:]</span> <span class="n">arr</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="sd">&#34;&#34;&#34;處理 2D double 陣列&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">i</span><span class="p">,</span> <span class="nf">j</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">rows</span> <span class="o">=</span> <span class="n">arr</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">cols</span> <span class="o">=</span> <span class="n">arr</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">cdef</span> <span class="kt">double</span> <span class="nf">total</span> <span class="o">=</span> <span class="mf">0.0</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">rows</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">cols</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">            <span class="n">total</span> <span class="o">+=</span> <span class="n">arr</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="k">return</span> <span class="n">total</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c"># 使用</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c"># import numpy as np</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c"># data = np.random.rand(100, 100)</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c"># result = process_array(data)</span></span></span></code></pre></div><h3 id="矩陣運算範例">矩陣運算範例</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># matrix_ops.pyx</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">cimport</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">cnp</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">cimport</span> <span class="nn">cython</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nd">@cython</span><span class="o">.</span><span class="n">boundscheck</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="nd">@cython</span><span class="o">.</span><span class="n">wraparound</span><span class="p">(</span><span class="bp">False</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="k">def</span> <span class="nf">matrix_multiply</span><span class="p">(</span><span class="n">double</span><span class="p">[:,</span> <span class="p">:]</span> <span class="n">A</span><span class="p">,</span> <span class="n">double</span><span class="p">[:,</span> <span class="p">:]</span> <span class="n">B</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="sd">&#34;&#34;&#34;矩陣乘法 C = A @ B&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">i</span><span class="p">,</span> <span class="nf">j</span><span class="p">,</span> <span class="nf">k</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">m</span> <span class="o">=</span> <span class="n">A</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">n</span> <span class="o">=</span> <span class="n">A</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">p</span> <span class="o">=</span> <span class="n">B</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mf">1</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">if</span> <span class="n">B</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mf">0</span><span class="p">]</span> <span class="o">!=</span> <span class="n">n</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="k">raise</span> <span class="ne">ValueError</span><span class="p">(</span><span class="s">&#34;矩陣維度不匹配&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">cdef</span> <span class="kt">double</span>[<span class="p">:,</span> <span class="p">:]</span> <span class="n">C</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">zeros</span><span class="p">((</span><span class="n">m</span><span class="p">,</span> <span class="n">p</span><span class="p">),</span> <span class="n">dtype</span><span class="o">=</span><span class="n">np</span><span class="o">.</span><span class="n">float64</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">p</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">            <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">                <span class="n">C</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span> <span class="o">+=</span> <span class="n">A</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="n">B</span><span class="p">[</span><span class="n">k</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="k">return</span> <span class="n">np</span><span class="o">.</span><span class="n">asarray</span><span class="p">(</span><span class="n">C</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">
</span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="c"># 注意：這只是教學範例</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="c"># 實際應用應使用 numpy.dot 或 BLAS</span></span></span></code></pre></div><h3 id="效能比較">效能比較</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">numpy</span> <span class="k">as</span> <span class="nn">np</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">timeit</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 假設已編譯 matrix_ops</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"># from matrix_ops import matrix_multiply</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="k">def</span> <span class="nf">benchmark</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">A</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">rand</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">B</span> <span class="o">=</span> <span class="n">np</span><span class="o">.</span><span class="n">random</span><span class="o">.</span><span class="n">rand</span><span class="p">(</span><span class="mi">100</span><span class="p">,</span> <span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="c1"># NumPy（使用 BLAS）</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">t1</span> <span class="o">=</span> <span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="n">A</span> <span class="o">@</span> <span class="n">B</span><span class="p">,</span> <span class="n">number</span><span class="o">=</span><span class="mi">100</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="c1"># Cython（我們的實現）</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="c1"># t2 = timeit.timeit(lambda: matrix_multiply(A, B), number=100)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="c1"># 純 Python</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">def</span> <span class="nf">py_matmul</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="n">m</span><span class="p">,</span> <span class="n">n</span> <span class="o">=</span> <span class="n">A</span><span class="o">.</span><span class="n">shape</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="n">p</span> <span class="o">=</span> <span class="n">B</span><span class="o">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="n">C</span> <span class="o">=</span> <span class="p">[[</span><span class="mf">0.0</span><span class="p">]</span> <span class="o">*</span> <span class="n">p</span> <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">m</span><span class="p">)]</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">m</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">            <span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">p</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">                <span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">                    <span class="n">C</span><span class="p">[</span><span class="n">i</span><span class="p">][</span><span class="n">j</span><span class="p">]</span> <span class="o">+=</span> <span class="n">A</span><span class="p">[</span><span class="n">i</span><span class="p">,</span> <span class="n">k</span><span class="p">]</span> <span class="o">*</span> <span class="n">B</span><span class="p">[</span><span class="n">k</span><span class="p">,</span> <span class="n">j</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="k">return</span> <span class="n">C</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="n">t3</span> <span class="o">=</span> <span class="n">timeit</span><span class="o">.</span><span class="n">timeit</span><span class="p">(</span><span class="k">lambda</span><span class="p">:</span> <span class="n">py_matmul</span><span class="p">(</span><span class="n">A</span><span class="p">,</span> <span class="n">B</span><span class="p">),</span> <span class="n">number</span><span class="o">=</span><span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;NumPy (BLAS):  </span><span class="si">{</span><span class="n">t1</span><span class="si">:</span><span class="s2">.4f</span><span class="si">}</span><span class="s2">s&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="c1"># print(f&#34;Cython:        {t2:.4f}s&#34;)</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;Pure Python:   </span><span class="si">{</span><span class="n">t3</span><span class="si">:</span><span class="s2">.4f</span><span class="si">}</span><span class="s2">s (x1)&#34;</span><span class="p">)</span></span></span></code></pre></div><hr>
<h2 id="實作層包裝-c-函式庫">【實作層】包裝 C 函式庫</h2>
<h3 id="宣告外部函式">宣告外部函式</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># 宣告 C 標準函式庫函式</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">from</span> <span class="nn">libc.math</span> <span class="k">cimport</span> <span class="n">sqrt</span><span class="p">,</span> <span class="n">sin</span><span class="p">,</span> <span class="n">cos</span><span class="p">,</span> <span class="nb">pow</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">from</span> <span class="nn">libc.stdlib</span> <span class="k">cimport</span> <span class="n">malloc</span><span class="p">,</span> <span class="n">free</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">from</span> <span class="nn">libc.string</span> <span class="k">cimport</span> <span class="n">memcpy</span><span class="p">,</span> <span class="n">strlen</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">def</span> <span class="nf">compute_distance</span><span class="p">(</span><span class="n">double</span> <span class="n">x1</span><span class="p">,</span> <span class="n">double</span> <span class="n">y1</span><span class="p">,</span> <span class="n">double</span> <span class="n">x2</span><span class="p">,</span> <span class="n">double</span> <span class="n">y2</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="sd">&#34;&#34;&#34;使用 C 的 sqrt&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">cdef</span> <span class="kt">double</span> <span class="nf">dx</span> <span class="o">=</span> <span class="n">x2</span> <span class="o">-</span> <span class="n">x1</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">cdef</span> <span class="kt">double</span> <span class="nf">dy</span> <span class="o">=</span> <span class="n">y2</span> <span class="o">-</span> <span class="n">y1</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">return</span> <span class="n">sqrt</span><span class="p">(</span><span class="n">dx</span> <span class="o">*</span> <span class="n">dx</span> <span class="o">+</span> <span class="n">dy</span> <span class="o">*</span> <span class="n">dy</span><span class="p">)</span></span></span></code></pre></div><h3 id="宣告自訂-c-函式庫">宣告自訂 C 函式庫</h3>
<p>假設有 C 標頭檔 <code>mylib.h</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">// mylib.h
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="k">typedef</span> <span class="k">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="kt">double</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">,</span> <span class="n">z</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="p">}</span> <span class="n">Vector3D</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="kt">double</span> <span class="nf">vector_length</span><span class="p">(</span><span class="n">Vector3D</span><span class="o">*</span> <span class="n">v</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="n">Vector3D</span> <span class="nf">vector_add</span><span class="p">(</span><span class="n">Vector3D</span><span class="o">*</span> <span class="n">a</span><span class="p">,</span> <span class="n">Vector3D</span><span class="o">*</span> <span class="n">b</span><span class="p">);</span></span></span></code></pre></div><p>建立 Cython 宣告檔 <code>mylib.pxd</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln">1</span><span class="cl"><span class="c"># mylib.pxd</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="k">cdef</span> <span class="kr">extern</span> <span class="k">from</span> <span class="s">&#34;mylib.h&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="k">ctypedef</span> <span class="k">struct</span> <span class="nc">Vector3D</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">        <span class="n">double</span> <span class="n">x</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">        <span class="n">double</span> <span class="n">y</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">        <span class="n">double</span> <span class="n">z</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">
</span></span><span class="line"><span class="ln">8</span><span class="cl">    <span class="n">double</span> <span class="n">vector_length</span><span class="p">(</span><span class="n">Vector3D</span><span class="o">*</span> <span class="n">v</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">9</span><span class="cl">    <span class="n">Vector3D</span> <span class="n">vector_add</span><span class="p">(</span><span class="n">Vector3D</span><span class="o">*</span> <span class="n">a</span><span class="p">,</span> <span class="n">Vector3D</span><span class="o">*</span> <span class="n">b</span><span class="p">)</span></span></span></code></pre></div><p>使用宣告：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># mylib_wrapper.pyx</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="k">from</span> <span class="nn">mylib</span> <span class="k">cimport</span> <span class="n">Vector3D</span><span class="p">,</span> <span class="n">vector_length</span><span class="p">,</span> <span class="n">vector_add</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">cdef</span> <span class="k">class</span> <span class="nf">PyVector3D</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="sd">&#34;&#34;&#34;Python 包裝類別&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="k">cdef</span> <span class="kt">Vector3D</span> <span class="nf">_vec</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">double</span> <span class="n">x</span><span class="p">,</span> <span class="n">double</span> <span class="n">y</span><span class="p">,</span> <span class="n">double</span> <span class="n">z</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_vec</span><span class="o">.</span><span class="n">x</span> <span class="o">=</span> <span class="n">x</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_vec</span><span class="o">.</span><span class="n">y</span> <span class="o">=</span> <span class="n">y</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_vec</span><span class="o">.</span><span class="n">z</span> <span class="o">=</span> <span class="n">z</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="nd">@property</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="k">def</span> <span class="nf">x</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_vec</span><span class="o">.</span><span class="n">x</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="nd">@property</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">def</span> <span class="nf">y</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_vec</span><span class="o">.</span><span class="n">y</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="nd">@property</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="k">def</span> <span class="nf">z</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_vec</span><span class="o">.</span><span class="n">z</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="k">def</span> <span class="nf">length</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="k">return</span> <span class="n">vector_length</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="o">.</span><span class="n">_vec</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="k">def</span> <span class="nf">__add__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">PyVector3D</span> <span class="n">other</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="k">cdef</span> <span class="kt">Vector3D</span> <span class="nf">result</span> <span class="o">=</span> <span class="n">vector_add</span><span class="p">(</span><span class="o">&amp;</span><span class="bp">self</span><span class="o">.</span><span class="n">_vec</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">other</span><span class="o">.</span><span class="n">_vec</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="k">return</span> <span class="n">PyVector3D</span><span class="p">(</span><span class="n">result</span><span class="o">.</span><span class="n">x</span><span class="p">,</span> <span class="n">result</span><span class="o">.</span><span class="n">y</span><span class="p">,</span> <span class="n">result</span><span class="o">.</span><span class="n">z</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="k">def</span> <span class="nf">__repr__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">        <span class="k">return</span> <span class="n">f</span><span class="s">&#34;Vector3D({self.x}, {self.y}, {self.z})&#34;</span></span></span></code></pre></div><h3 id="記憶體管理">記憶體管理</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cython" data-lang="cython"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="k">from</span> <span class="nn">libc.stdlib</span> <span class="k">cimport</span> <span class="n">malloc</span><span class="p">,</span> <span class="n">free</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="k">cdef</span> <span class="k">class</span> <span class="nf">DynamicArray</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="sd">&#34;&#34;&#34;管理動態分配記憶體的範例&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">cdef</span> <span class="kt">double</span>* <span class="nf">data</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">size</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">def</span> <span class="nf">__cinit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">int</span> <span class="n">size</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="sd">&#34;&#34;&#34;C 層級初始化，保證在 __init__ 之前執行&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">size</span> <span class="o">=</span> <span class="n">size</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">=</span> <span class="o">&lt;</span><span class="n">double</span><span class="o">*&gt;</span><span class="n">malloc</span><span class="p">(</span><span class="n">size</span> <span class="o">*</span> <span class="n">sizeof</span><span class="p">(</span><span class="n">double</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">==</span> <span class="bp">NULL</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">            <span class="k">raise</span> <span class="ne">MemoryError</span><span class="p">(</span><span class="s">&#34;無法分配記憶體&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">def</span> <span class="nf">__dealloc__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="sd">&#34;&#34;&#34;C 層級解構，保證釋放記憶體&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">        <span class="k">if</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span> <span class="o">!=</span> <span class="bp">NULL</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">            <span class="n">free</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">int</span> <span class="n">size</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">        <span class="sd">&#34;&#34;&#34;Python 層級初始化&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="k">cdef</span> <span class="kt">int</span> <span class="nf">i</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">            <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mf">0.0</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="k">def</span> <span class="nf">__getitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">int</span> <span class="n">index</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="k">if</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mf">0</span> <span class="ow">or</span> <span class="n">index</span> <span class="o">&gt;=</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">            <span class="k">raise</span> <span class="ne">IndexError</span><span class="p">(</span><span class="s">&#34;索引超出範圍&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="n">index</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="k">def</span> <span class="nf">__setitem__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">int</span> <span class="n">index</span><span class="p">,</span> <span class="n">double</span> <span class="n">value</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">        <span class="k">if</span> <span class="n">index</span> <span class="o">&lt;</span> <span class="mf">0</span> <span class="ow">or</span> <span class="n">index</span> <span class="o">&gt;=</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">            <span class="k">raise</span> <span class="ne">IndexError</span><span class="p">(</span><span class="s">&#34;索引超出範圍&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">data</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">=</span> <span class="n">value</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="k">def</span> <span class="nf">__len__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">size</span></span></span></code></pre></div><hr>
<h2 id="進階pure-python-模式">【進階】Pure Python 模式</h2>
<h3 id="使用型別註解">使用型別註解</h3>
<p>從 Cython 3.0 開始，支援純 Python 語法：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># pure_example.py（純 Python 檔案）</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">cython</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nd">@cython.cfunc</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">def</span> <span class="nf">c_function</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">cython</span><span class="o">.</span><span class="n">int</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">cython</span><span class="o">.</span><span class="n">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">cython</span><span class="o">.</span><span class="n">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="s2">&#34;&#34;&#34;等同於 cdef int c_function(int x, int y)&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">return</span> <span class="n">x</span> <span class="o">+</span> <span class="n">y</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="nd">@cython.ccall</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="k">def</span> <span class="nf">hybrid_function</span><span class="p">(</span><span class="n">x</span><span class="p">:</span> <span class="n">cython</span><span class="o">.</span><span class="n">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">cython</span><span class="o">.</span><span class="n">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="s2">&#34;&#34;&#34;等同於 cpdef int hybrid_function(int x)&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">return</span> <span class="n">c_function</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">x</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="k">def</span> <span class="nf">public_api</span><span class="p">(</span><span class="n">n</span><span class="p">:</span> <span class="n">cython</span><span class="o">.</span><span class="n">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="n">cython</span><span class="o">.</span><span class="n">long</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="s2">&#34;&#34;&#34;普通 Python 函式，但有型別最佳化&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="n">total</span><span class="p">:</span> <span class="n">cython</span><span class="o">.</span><span class="n">long</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="n">i</span><span class="p">:</span> <span class="n">cython</span><span class="o">.</span><span class="n">int</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="n">total</span> <span class="o">+=</span> <span class="n">hybrid_function</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="k">return</span> <span class="n">total</span></span></span></code></pre></div><h3 id="優點">優點</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Pure Python 模式的好處：
</span></span><span class="line"><span class="ln">2</span><span class="cl">1. 不需要 .pyx 檔案，直接用 .py
</span></span><span class="line"><span class="ln">3</span><span class="cl">2. IDE 支援更好（型別提示）
</span></span><span class="line"><span class="ln">4</span><span class="cl">3. 可以同時作為 Python 和 Cython 使用
</span></span><span class="line"><span class="ln">5</span><span class="cl">4. 測試更容易（不需編譯就能跑 Python）</span></span></code></pre></div><hr>
<h2 id="建構現代化建構方式">【建構】現代化建構方式</h2>
<h3 id="使用-pyprojecttoml">使用 pyproject.toml</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># pyproject.toml</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="p">[</span><span class="nx">build-system</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="nx">requires</span> <span class="p">=</span> <span class="p">[</span><span class="s2">&#34;setuptools&gt;=61.0&#34;</span><span class="p">,</span> <span class="s2">&#34;cython&gt;=3.0&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nx">build-backend</span> <span class="p">=</span> <span class="s2">&#34;setuptools.build_meta&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="p">[</span><span class="nx">project</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="nx">name</span> <span class="p">=</span> <span class="s2">&#34;my-cython-package&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="nx">version</span> <span class="p">=</span> <span class="s2">&#34;0.1.0&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">[</span><span class="nx">tool</span><span class="p">.</span><span class="nx">setuptools</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="nx">ext-modules</span> <span class="p">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="p">{</span><span class="nx">name</span> <span class="p">=</span> <span class="s2">&#34;my_module&#34;</span><span class="p">,</span> <span class="nx">sources</span> <span class="p">=</span> <span class="p">[</span><span class="s2">&#34;src/my_module.pyx&#34;</span><span class="p">]}</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="p">]</span></span></span></code></pre></div><h3 id="使用-meson-python">使用 meson-python</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="ln">1</span><span class="cl"><span class="c"># pyproject.toml</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="p">[</span><span class="nx">build-system</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nx">requires</span> <span class="p">=</span> <span class="p">[</span><span class="s2">&#34;meson-python&#34;</span><span class="p">,</span> <span class="s2">&#34;cython&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="nx">build-backend</span> <span class="p">=</span> <span class="s2">&#34;mesonpy&#34;</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="p">[</span><span class="nx">project</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="nx">name</span> <span class="p">=</span> <span class="s2">&#34;my-cython-package&#34;</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="nx">version</span> <span class="p">=</span> <span class="s2">&#34;0.1.0&#34;</span></span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-meson" data-lang="meson"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># meson.build</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w"></span><span class="nb">project</span><span class="p">(</span><span class="s">&#39;my-cython-package&#39;</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;cython&#39;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w"></span><span class="n">py</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nn">import</span><span class="p">(</span><span class="s">&#39;python&#39;</span><span class="p">).</span><span class="n">find_installation</span><span class="p">()</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w"></span><span class="n">py</span><span class="p">.</span><span class="n">extension_module</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">    </span><span class="s">&#39;my_module&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">    </span><span class="s">&#39;src/my_module.pyx&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">    </span><span class="n">install</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w"></span><span class="p">)</span></span></span></code></pre></div><hr>
<h2 id="思考題">思考題</h2>
<ol>
<li>為什麼 cdef 函式比 def 函式快？從呼叫協議的角度解釋。</li>
<li>在什麼情況下，Cython 的效能提升最明顯？什麼情況下提升有限？</li>
<li>如何決定哪些函式應該用 cdef、cpdef 還是 def？</li>
</ol>
<h2 id="實作練習">實作練習</h2>
<ol>
<li>將入門系列效能章節的 <code>is_prime</code> 函式用 Cython 改寫，比較效能差異</li>
<li>使用 Cython 實現一個簡單的 LRU Cache，與 <code>functools.lru_cache</code> 比較效能</li>
<li>包裝一個簡單的 C 函式庫（如 zlib）並在 Python 中使用</li>
</ol>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://cython.readthedocs.io/">Cython 官方文件</a></li>
<li><a href="https://cython.readthedocs.io/en/latest/src/userguide/numpy_tutorial.html">Cython 最佳實踐</a></li>
<li><a href="https://www.oreilly.com/library/view/cython/9781491901731/">Kurt Smith - Cython: A Guide for Python Programmers</a></li>
</ul>
<hr>
<p><em>上一章：<a href="/blog/python-advanced/05-c-extensions/ctypes-cffi/" data-link-title="4.1 ctypes 與 cffi：動態綁定" data-link-desc="使用 ctypes 和 cffi 呼叫 C 函式庫">ctypes 與 cffi</a></em>
<em>下一章：<a href="/blog/python-advanced/05-c-extensions/pybind11/" data-link-title="4.3 pybind11：現代 C&#43;&#43; 綁定" data-link-desc="使用 pybind11 建立 Python 與 C&#43;&#43; 的綁定">pybind11</a></em></p>
]]></content:encoded></item><item><title>案例：pybind11 綁定 C++ 類別</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/pybind11-cpp-binding/</link><pubDate>Wed, 21 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/pybind11-cpp-binding/</guid><description>&lt;p>本案例展示如何使用 pybind11 將 C++ 類別完整綁定到 Python，包含建構子、方法、屬性、運算子重載，以及記憶體管理與生命週期控制。&lt;/p>
&lt;h2 id="先備知識">先備知識&lt;/h2>
&lt;ul>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/pybind11/" data-link-title="4.3 pybind11：現代 C&amp;#43;&amp;#43; 綁定" data-link-desc="使用 pybind11 建立 Python 與 C&amp;#43;&amp;#43; 的綁定">4.3 pybind11：現代 C++ 綁定&lt;/a>&lt;/li>
&lt;li>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python&lt;/a>&lt;/li>
&lt;/ul>
&lt;h2 id="問題背景">問題背景&lt;/h2>
&lt;h3 id="使用情境">使用情境&lt;/h3>
&lt;p>在以下情境中，你可能需要在 Python 中使用 C++ 類別：&lt;/p>
&lt;ol>
&lt;li>&lt;strong>複用現有 C++ 程式庫&lt;/strong>：公司有成熟的 C++ 資料結構或演算法，想在 Python 專案中使用&lt;/li>
&lt;li>&lt;strong>效能敏感的資料處理&lt;/strong>：需要高效的記憶體管理和計算效能&lt;/li>
&lt;li>&lt;strong>自訂資料結構&lt;/strong>：標準 Python 容器無法滿足特定需求&lt;/li>
&lt;/ol>
&lt;h3 id="設計目標">設計目標&lt;/h3>
&lt;p>本案例將建立一個 &lt;code>StringProcessor&lt;/code> 類別，展示：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">StringProcessor 功能：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">├── 建構子：支援預設和參數化初始化
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">├── 方法：字串處理（大小寫轉換、統計、搜尋）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">├── 屬性：可讀寫的狀態屬性
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">├── 運算子重載：+ 運算子串接、[] 索引存取
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">├── 記憶體管理：正確處理物件生命週期
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">└── 效能優化：避免不必要的記憶體複製&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="實作步驟">實作步驟&lt;/h2>
&lt;h3 id="步驟-1專案結構">步驟 1：專案結構&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">pybind11_string_processor/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">├── CMakeLists.txt
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">├── setup.py
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">├── src/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">│ ├── string_processor.hpp # C++ 標頭檔
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">│ ├── string_processor.cpp # C++ 實作
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">│ └── bindings.cpp # pybind11 綁定
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">├── tests/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">│ └── test_string_processor.py
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">└── benchmark.py&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="步驟-2c-類別定義">步驟 2：C++ 類別定義&lt;/h3>
&lt;p>首先，建立 C++ 類別的標頭檔：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">// src/string_processor.hpp
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#ifndef STRING_PROCESSOR_HPP
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="cp">#define STRING_PROCESSOR_HPP
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;string&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;unordered_map&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;memory&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;stdexcept&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 10&lt;/span>&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 11&lt;/span>&lt;span class="cl">&lt;span class="cm">/**
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 12&lt;/span>&lt;span class="cl">&lt;span class="cm"> * StringProcessor: 高效能字串處理類別
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 13&lt;/span>&lt;span class="cl">&lt;span class="cm"> *
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 14&lt;/span>&lt;span class="cl">&lt;span class="cm"> * 提供字串操作、統計分析和搜尋功能。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 15&lt;/span>&lt;span class="cl">&lt;span class="cm"> * 設計用於展示 pybind11 的類別綁定特性。
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 16&lt;/span>&lt;span class="cl">&lt;span class="cm"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 17&lt;/span>&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">StringProcessor&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 18&lt;/span>&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 19&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 20&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 建構子與解構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 21&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 22&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 23&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 預設建構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 24&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 25&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 26&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 參數化建構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 27&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">explicit&lt;/span> &lt;span class="nf">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 28&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 29&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 複製建構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 30&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 31&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 32&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 移動建構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 33&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">noexcept&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 34&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 35&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 解構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 36&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="o">~&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 37&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 38&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 39&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 基本方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 40&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 41&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 42&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 取得內容
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 43&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 44&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 45&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 設定內容
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 46&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">set_content&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 47&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 48&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 取得長度
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 49&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="nf">length&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 50&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 51&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 是否為空
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 52&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="nf">empty&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">();&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 53&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 54&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 55&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 字串處理方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 56&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 57&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 58&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 轉換為大寫
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 59&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">to_upper&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 60&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 61&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 轉換為小寫
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 62&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">to_lower&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 63&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 64&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 反轉字串
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 65&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">reverse&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 66&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 67&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 移除前後空白
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 68&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">trim&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 69&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 70&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 分割字串
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 71&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">delimiter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34; &amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 72&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 73&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 取代子字串
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 74&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">old_str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 75&lt;/span>&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">new_str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 76&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 77&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 78&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 統計分析方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 79&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 80&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 81&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 字元頻率統計
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 82&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unordered_map&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">char&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">char_frequency&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 83&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 84&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 單字計數
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 85&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="nf">word_count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 86&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 87&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 子字串出現次數
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 88&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="nf">count_occurrences&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 89&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 90&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 91&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 搜尋方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 92&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 93&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 94&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 搜尋子字串位置（找不到回傳 -1）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 95&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="nf">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 96&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 97&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 搜尋所有出現位置
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 98&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">size_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 99&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">100&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 是否包含子字串
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">101&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="nf">contains&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">102&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">103&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 是否以指定字串開頭
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">104&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="nf">starts_with&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">prefix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">105&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">106&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 是否以指定字串結尾
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">107&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="nf">ends_with&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">suffix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">108&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">109&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">110&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 運算子重載
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">111&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">112&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">113&lt;/span>&lt;span class="cl"> &lt;span class="c1">// + 運算子：串接
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">114&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">StringProcessor&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">115&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">116&lt;/span>&lt;span class="cl"> &lt;span class="c1">// += 運算子：原地串接
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">117&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">118&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">119&lt;/span>&lt;span class="cl"> &lt;span class="c1">// [] 運算子：索引存取
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">120&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="p">[](&lt;/span>&lt;span class="n">size_t&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">121&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">122&lt;/span>&lt;span class="cl"> &lt;span class="c1">// == 運算子：相等比較
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">123&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">124&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">125&lt;/span>&lt;span class="cl"> &lt;span class="c1">// != 運算子：不等比較
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">126&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">bool&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">!=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">127&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">128&lt;/span>&lt;span class="cl"> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">129&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// 指派運算子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">130&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">131&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">132&lt;/span>&lt;span class="cl"> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">133&lt;/span>&lt;span class="cl"> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="k">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">noexcept&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">134&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">135&lt;/span>&lt;span class="cl">&lt;span class="k">private&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">136&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">137&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">138&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 處理計數器（用於展示狀態追蹤）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">139&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">mutable&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">operation_count_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">140&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">141&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 輔助方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">142&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">increment_operation_count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="o">++&lt;/span>&lt;span class="n">operation_count_&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">143&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">144&lt;/span>&lt;span class="cl">&lt;span class="k">public&lt;/span>&lt;span class="o">:&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">145&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 取得操作計數（用於效能分析）
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">146&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">operation_count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">operation_count_&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">147&lt;/span>&lt;span class="cl"> &lt;span class="kt">void&lt;/span> &lt;span class="nf">reset_operation_count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="n">operation_count_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">148&lt;/span>&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">149&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">150&lt;/span>&lt;span class="cl">&lt;span class="cp">#endif &lt;/span>&lt;span class="c1">// STRING_PROCESSOR_HPP
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="步驟-3c-實作">步驟 3：C++ 實作&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">// src/string_processor.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;#34;string_processor.hpp&amp;#34;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;algorithm&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;cctype&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;sstream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="c1">// 建構子與解構子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 10&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 11&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 12&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 13&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 14&lt;/span>&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 15&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 16&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 17&lt;/span>&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">operation_count_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 18&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 19&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">noexcept&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 20&lt;/span>&lt;span class="cl"> &lt;span class="o">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">move&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">)),&lt;/span> &lt;span class="n">operation_count_&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 21&lt;/span>&lt;span class="cl"> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">clear&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 22&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 23&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 24&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::~&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">default&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 25&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 26&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 27&lt;/span>&lt;span class="cl">&lt;span class="c1">// 基本方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 28&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 29&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 30&lt;/span>&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">set_content&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 31&lt;/span>&lt;span class="cl"> &lt;span class="n">content_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 32&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 33&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 34&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 35&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 36&lt;/span>&lt;span class="cl">&lt;span class="c1">// 字串處理方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 37&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 38&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 39&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">to_upper&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 40&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 41&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 42&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">transform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">end&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 43&lt;/span>&lt;span class="cl"> &lt;span class="p">[](&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="n">c&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">toupper&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">c&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 44&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 45&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 46&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 47&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">to_lower&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 48&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 49&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 50&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">transform&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">end&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 51&lt;/span>&lt;span class="cl"> &lt;span class="p">[](&lt;/span>&lt;span class="kt">unsigned&lt;/span> &lt;span class="kt">char&lt;/span> &lt;span class="n">c&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">tolower&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">c&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="p">});&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 52&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 53&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 54&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 55&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">reverse&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 56&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 57&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 58&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">reverse&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">begin&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">end&lt;/span>&lt;span class="p">());&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 59&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 60&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 61&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 62&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">trim&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 63&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 64&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find_first_not_of&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34; &lt;/span>&lt;span class="se">\t\n\r\f\v&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 65&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">start&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 66&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s">&amp;#34;&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 67&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 68&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">end&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find_last_not_of&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34; &lt;/span>&lt;span class="se">\t\n\r\f\v&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 69&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">substr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">start&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">end&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 70&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 71&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 72&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">split&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">delimiter&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 73&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 74&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 75&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 76&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">delimiter&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 77&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 空分隔符：按字元分割
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 78&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">char&lt;/span> &lt;span class="nl">c&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 79&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">c&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 80&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 81&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 82&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 83&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 84&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 85&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">end&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">delimiter&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 86&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 87&lt;/span>&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">end&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 88&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">substr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">start&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">end&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 89&lt;/span>&lt;span class="cl"> &lt;span class="n">start&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">end&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">delimiter&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 90&lt;/span>&lt;span class="cl"> &lt;span class="n">end&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">delimiter&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 91&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 92&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 93&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">substr&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">start&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 94&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 95&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 96&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 97&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">old_str&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 98&lt;/span>&lt;span class="cl"> &lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">new_str&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 99&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">100&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">old_str&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">101&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">102&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">103&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">104&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">result&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">105&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">106&lt;/span>&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">old_str&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pos&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">107&lt;/span>&lt;span class="cl"> &lt;span class="n">result&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">replace&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">old_str&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">new_str&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">108&lt;/span>&lt;span class="cl"> &lt;span class="n">pos&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">new_str&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">109&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">110&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">result&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">111&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">112&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">113&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">114&lt;/span>&lt;span class="cl">&lt;span class="c1">// 統計分析方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">115&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">116&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">117&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unordered_map&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">char&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">char_frequency&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">118&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">119&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unordered_map&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">char&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">freq&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">120&lt;/span>&lt;span class="cl"> &lt;span class="k">for&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="kt">char&lt;/span> &lt;span class="nl">c&lt;/span> &lt;span class="p">:&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">121&lt;/span>&lt;span class="cl"> &lt;span class="n">freq&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">c&lt;/span>&lt;span class="p">]&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">122&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">123&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">freq&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">124&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">125&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">126&lt;/span>&lt;span class="cl">&lt;span class="n">size_t&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">word_count&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">127&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">128&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">129&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">130&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">131&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">132&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">istringstream&lt;/span> &lt;span class="n">iss&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">133&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">134&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">word&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">135&lt;/span>&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">iss&lt;/span> &lt;span class="o">&amp;gt;&amp;gt;&lt;/span> &lt;span class="n">word&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">136&lt;/span>&lt;span class="cl"> &lt;span class="n">count&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">137&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">138&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">count&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">139&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">140&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">141&lt;/span>&lt;span class="cl">&lt;span class="n">size_t&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">count_occurrences&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">142&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">143&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">144&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">145&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">146&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">147&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">count&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">148&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">149&lt;/span>&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pos&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">150&lt;/span>&lt;span class="cl"> &lt;span class="n">count&lt;/span>&lt;span class="o">++&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">151&lt;/span>&lt;span class="cl"> &lt;span class="n">pos&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">152&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">153&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">count&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">154&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">155&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">156&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">157&lt;/span>&lt;span class="cl">&lt;span class="c1">// 搜尋方法
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">158&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">159&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">160&lt;/span>&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">size_t&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">161&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">162&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">start&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">163&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">pos&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">?&lt;/span> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span> &lt;span class="o">:&lt;/span> &lt;span class="k">static_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">164&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">165&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">166&lt;/span>&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">size_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">find_all&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">167&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">168&lt;/span>&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">size_t&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">positions&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">169&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">empty&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">170&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">positions&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">171&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">172&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">173&lt;/span>&lt;span class="cl"> &lt;span class="n">size_t&lt;/span> &lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">174&lt;/span>&lt;span class="cl"> &lt;span class="k">while&lt;/span> &lt;span class="p">((&lt;/span>&lt;span class="n">pos&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">pos&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">175&lt;/span>&lt;span class="cl"> &lt;span class="n">positions&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">pos&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">176&lt;/span>&lt;span class="cl"> &lt;span class="n">pos&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">177&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">178&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">positions&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">179&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">180&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">181&lt;/span>&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">contains&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">182&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">183&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">find&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">substring&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">npos&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">184&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">185&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">186&lt;/span>&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">starts_with&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">prefix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">187&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">188&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">prefix&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">189&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">190&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">191&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">compare&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">prefix&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">prefix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">192&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">193&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">194&lt;/span>&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">ends_with&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">suffix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">195&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">196&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">suffix&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">197&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">false&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">198&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">199&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">compare&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">-&lt;/span> &lt;span class="n">suffix&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">(),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">200&lt;/span>&lt;span class="cl"> &lt;span class="n">suffix&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">(),&lt;/span> &lt;span class="n">suffix&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">201&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">202&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">203&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">204&lt;/span>&lt;span class="cl">&lt;span class="c1">// 運算子重載
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">205&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">206&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">207&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">+&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">208&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">209&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nf">StringProcessor&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content_&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">210&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">211&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">212&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">213&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">214&lt;/span>&lt;span class="cl"> &lt;span class="n">content_&lt;/span> &lt;span class="o">+=&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">215&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="k">this&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">216&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">217&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">218&lt;/span>&lt;span class="cl">&lt;span class="kt">char&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="p">[](&lt;/span>&lt;span class="n">size_t&lt;/span> &lt;span class="n">index&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">219&lt;/span>&lt;span class="cl"> &lt;span class="n">increment_operation_count&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">220&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">index&lt;/span> &lt;span class="o">&amp;gt;=&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">length&lt;/span>&lt;span class="p">())&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">221&lt;/span>&lt;span class="cl"> &lt;span class="k">throw&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">out_of_range&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Index out of range: &amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">to_string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">index&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">222&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">223&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="n">index&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">224&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">225&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">226&lt;/span>&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">==&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">227&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span> &lt;span class="o">==&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">228&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">229&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">230&lt;/span>&lt;span class="cl">&lt;span class="kt">bool&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">!=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">const&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">231&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">content_&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">232&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">233&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">234&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">235&lt;/span>&lt;span class="cl">&lt;span class="c1">// 指派運算子
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">236&lt;/span>&lt;span class="cl">&lt;span class="c1">// ========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">237&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">238&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">239&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">this&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">240&lt;/span>&lt;span class="cl"> &lt;span class="n">content_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">241&lt;/span>&lt;span class="cl"> &lt;span class="n">operation_count_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">242&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">243&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="k">this&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">244&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">245&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">246&lt;/span>&lt;span class="cl">&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="k">operator&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">StringProcessor&lt;/span>&lt;span class="o">&amp;amp;&amp;amp;&lt;/span> &lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="k">noexcept&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">247&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="k">this&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">other&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">248&lt;/span>&lt;span class="cl"> &lt;span class="n">content_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">move&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">249&lt;/span>&lt;span class="cl"> &lt;span class="n">operation_count_&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">250&lt;/span>&lt;span class="cl"> &lt;span class="n">other&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">content_&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">clear&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">251&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">252&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="k">this&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">253&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="步驟-4pybind11-綁定">步驟 4：pybind11 綁定&lt;/h3>
&lt;p>這是最關鍵的部分，將 C++ 類別暴露給 Python：&lt;/p></description><content:encoded><![CDATA[<p>本案例展示如何使用 pybind11 將 C++ 類別完整綁定到 Python，包含建構子、方法、屬性、運算子重載，以及記憶體管理與生命週期控制。</p>
<h2 id="先備知識">先備知識</h2>
<ul>
<li><a href="/blog/python-advanced/05-c-extensions/pybind11/" data-link-title="4.3 pybind11：現代 C&#43;&#43; 綁定" data-link-desc="使用 pybind11 建立 Python 與 C&#43;&#43; 的綁定">4.3 pybind11：現代 C++ 綁定</a></li>
<li><a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python</a></li>
</ul>
<h2 id="問題背景">問題背景</h2>
<h3 id="使用情境">使用情境</h3>
<p>在以下情境中，你可能需要在 Python 中使用 C++ 類別：</p>
<ol>
<li><strong>複用現有 C++ 程式庫</strong>：公司有成熟的 C++ 資料結構或演算法，想在 Python 專案中使用</li>
<li><strong>效能敏感的資料處理</strong>：需要高效的記憶體管理和計算效能</li>
<li><strong>自訂資料結構</strong>：標準 Python 容器無法滿足特定需求</li>
</ol>
<h3 id="設計目標">設計目標</h3>
<p>本案例將建立一個 <code>StringProcessor</code> 類別，展示：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">StringProcessor 功能：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── 建構子：支援預設和參數化初始化
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── 方法：字串處理（大小寫轉換、統計、搜尋）
</span></span><span class="line"><span class="ln">4</span><span class="cl">├── 屬性：可讀寫的狀態屬性
</span></span><span class="line"><span class="ln">5</span><span class="cl">├── 運算子重載：+ 運算子串接、[] 索引存取
</span></span><span class="line"><span class="ln">6</span><span class="cl">├── 記憶體管理：正確處理物件生命週期
</span></span><span class="line"><span class="ln">7</span><span class="cl">└── 效能優化：避免不必要的記憶體複製</span></span></code></pre></div><h2 id="實作步驟">實作步驟</h2>
<h3 id="步驟-1專案結構">步驟 1：專案結構</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">pybind11_string_processor/
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">├── CMakeLists.txt
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├── setup.py
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── src/
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">│   ├── string_processor.hpp    # C++ 標頭檔
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">│   ├── string_processor.cpp    # C++ 實作
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">│   └── bindings.cpp            # pybind11 綁定
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">├── tests/
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">│   └── test_string_processor.py
</span></span><span class="line"><span class="ln">10</span><span class="cl">└── benchmark.py</span></span></code></pre></div><h3 id="步驟-2c-類別定義">步驟 2：C++ 類別定義</h3>
<p>首先，建立 C++ 類別的標頭檔：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c1">// src/string_processor.hpp
</span></span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="c1"></span><span class="cp">#ifndef STRING_PROCESSOR_HPP
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="cp">#define STRING_PROCESSOR_HPP
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">  5</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;unordered_map&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;memory&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  9</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdexcept&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 11</span><span class="cl"><span class="cm">/**
</span></span></span><span class="line"><span class="ln"> 12</span><span class="cl"><span class="cm"> * StringProcessor: 高效能字串處理類別
</span></span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="cm"> *
</span></span></span><span class="line"><span class="ln"> 14</span><span class="cl"><span class="cm"> * 提供字串操作、統計分析和搜尋功能。
</span></span></span><span class="line"><span class="ln"> 15</span><span class="cl"><span class="cm"> * 設計用於展示 pybind11 的類別綁定特性。
</span></span></span><span class="line"><span class="ln"> 16</span><span class="cl"><span class="cm"> */</span>
</span></span><span class="line"><span class="ln"> 17</span><span class="cl"><span class="k">class</span> <span class="nc">StringProcessor</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 18</span><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="ln"> 19</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 20</span><span class="cl"><span class="c1"></span>    <span class="c1">// 建構子與解構子
</span></span></span><span class="line"><span class="ln"> 21</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 22</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 23</span><span class="cl">    <span class="c1">// 預設建構子
</span></span></span><span class="line"><span class="ln"> 24</span><span class="cl"><span class="c1"></span>    <span class="n">StringProcessor</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">
</span></span><span class="line"><span class="ln"> 26</span><span class="cl">    <span class="c1">// 參數化建構子
</span></span></span><span class="line"><span class="ln"> 27</span><span class="cl"><span class="c1"></span>    <span class="k">explicit</span> <span class="nf">StringProcessor</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">content</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 28</span><span class="cl">
</span></span><span class="line"><span class="ln"> 29</span><span class="cl">    <span class="c1">// 複製建構子
</span></span></span><span class="line"><span class="ln"> 30</span><span class="cl"><span class="c1"></span>    <span class="n">StringProcessor</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 31</span><span class="cl">
</span></span><span class="line"><span class="ln"> 32</span><span class="cl">    <span class="c1">// 移動建構子
</span></span></span><span class="line"><span class="ln"> 33</span><span class="cl"><span class="c1"></span>    <span class="n">StringProcessor</span><span class="p">(</span><span class="n">StringProcessor</span><span class="o">&amp;&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 34</span><span class="cl">
</span></span><span class="line"><span class="ln"> 35</span><span class="cl">    <span class="c1">// 解構子
</span></span></span><span class="line"><span class="ln"> 36</span><span class="cl"><span class="c1"></span>    <span class="o">~</span><span class="n">StringProcessor</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 37</span><span class="cl">
</span></span><span class="line"><span class="ln"> 38</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 39</span><span class="cl"><span class="c1"></span>    <span class="c1">// 基本方法
</span></span></span><span class="line"><span class="ln"> 40</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 41</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 42</span><span class="cl">    <span class="c1">// 取得內容
</span></span></span><span class="line"><span class="ln"> 43</span><span class="cl"><span class="c1"></span>    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">content</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">content_</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 44</span><span class="cl">
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">    <span class="c1">// 設定內容
</span></span></span><span class="line"><span class="ln"> 46</span><span class="cl"><span class="c1"></span>    <span class="kt">void</span> <span class="nf">set_content</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">content</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 47</span><span class="cl">
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">    <span class="c1">// 取得長度
</span></span></span><span class="line"><span class="ln"> 49</span><span class="cl"><span class="c1"></span>    <span class="n">size_t</span> <span class="nf">length</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">length</span><span class="p">();</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 50</span><span class="cl">
</span></span><span class="line"><span class="ln"> 51</span><span class="cl">    <span class="c1">// 是否為空
</span></span></span><span class="line"><span class="ln"> 52</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="nf">empty</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">empty</span><span class="p">();</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl">
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 55</span><span class="cl"><span class="c1"></span>    <span class="c1">// 字串處理方法
</span></span></span><span class="line"><span class="ln"> 56</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 57</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 58</span><span class="cl">    <span class="c1">// 轉換為大寫
</span></span></span><span class="line"><span class="ln"> 59</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_upper</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 60</span><span class="cl">
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">    <span class="c1">// 轉換為小寫
</span></span></span><span class="line"><span class="ln"> 62</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">to_lower</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">    <span class="c1">// 反轉字串
</span></span></span><span class="line"><span class="ln"> 65</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">reverse</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl">
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">    <span class="c1">// 移除前後空白
</span></span></span><span class="line"><span class="ln"> 68</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">trim</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 69</span><span class="cl">
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">    <span class="c1">// 分割字串
</span></span></span><span class="line"><span class="ln"> 71</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">split</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">delimiter</span> <span class="o">=</span> <span class="s">&#34; &#34;</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 72</span><span class="cl">
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">    <span class="c1">// 取代子字串
</span></span></span><span class="line"><span class="ln"> 74</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">replace</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">old_str</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">                        <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">new_str</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 76</span><span class="cl">
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 78</span><span class="cl"><span class="c1"></span>    <span class="c1">// 統計分析方法
</span></span></span><span class="line"><span class="ln"> 79</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 80</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 81</span><span class="cl">    <span class="c1">// 字元頻率統計
</span></span></span><span class="line"><span class="ln"> 82</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">char_frequency</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 83</span><span class="cl">
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">    <span class="c1">// 單字計數
</span></span></span><span class="line"><span class="ln"> 85</span><span class="cl"><span class="c1"></span>    <span class="n">size_t</span> <span class="nf">word_count</span><span class="p">()</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">    <span class="c1">// 子字串出現次數
</span></span></span><span class="line"><span class="ln"> 88</span><span class="cl"><span class="c1"></span>    <span class="n">size_t</span> <span class="nf">count_occurrences</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 91</span><span class="cl"><span class="c1"></span>    <span class="c1">// 搜尋方法
</span></span></span><span class="line"><span class="ln"> 92</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 93</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">    <span class="c1">// 搜尋子字串位置（找不到回傳 -1）
</span></span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="c1"></span>    <span class="kt">int</span> <span class="nf">find</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 96</span><span class="cl">
</span></span><span class="line"><span class="ln"> 97</span><span class="cl">    <span class="c1">// 搜尋所有出現位置
</span></span></span><span class="line"><span class="ln"> 98</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">size_t</span><span class="o">&gt;</span> <span class="n">find_all</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">
</span></span><span class="line"><span class="ln">100</span><span class="cl">    <span class="c1">// 是否包含子字串
</span></span></span><span class="line"><span class="ln">101</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="nf">contains</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">
</span></span><span class="line"><span class="ln">103</span><span class="cl">    <span class="c1">// 是否以指定字串開頭
</span></span></span><span class="line"><span class="ln">104</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="nf">starts_with</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">prefix</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">
</span></span><span class="line"><span class="ln">106</span><span class="cl">    <span class="c1">// 是否以指定字串結尾
</span></span></span><span class="line"><span class="ln">107</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="nf">ends_with</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">suffix</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">108</span><span class="cl">
</span></span><span class="line"><span class="ln">109</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">110</span><span class="cl"><span class="c1"></span>    <span class="c1">// 運算子重載
</span></span></span><span class="line"><span class="ln">111</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">112</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">113</span><span class="cl">    <span class="c1">// + 運算子：串接
</span></span></span><span class="line"><span class="ln">114</span><span class="cl"><span class="c1"></span>    <span class="n">StringProcessor</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">115</span><span class="cl">
</span></span><span class="line"><span class="ln">116</span><span class="cl">    <span class="c1">// += 運算子：原地串接
</span></span></span><span class="line"><span class="ln">117</span><span class="cl"><span class="c1"></span>    <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">+=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">
</span></span><span class="line"><span class="ln">119</span><span class="cl">    <span class="c1">// [] 運算子：索引存取
</span></span></span><span class="line"><span class="ln">120</span><span class="cl"><span class="c1"></span>    <span class="kt">char</span> <span class="k">operator</span><span class="p">[](</span><span class="n">size_t</span> <span class="n">index</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">121</span><span class="cl">
</span></span><span class="line"><span class="ln">122</span><span class="cl">    <span class="c1">// == 運算子：相等比較
</span></span></span><span class="line"><span class="ln">123</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">124</span><span class="cl">
</span></span><span class="line"><span class="ln">125</span><span class="cl">    <span class="c1">// != 運算子：不等比較
</span></span></span><span class="line"><span class="ln">126</span><span class="cl"><span class="c1"></span>    <span class="kt">bool</span> <span class="k">operator</span><span class="o">!=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">127</span><span class="cl">
</span></span><span class="line"><span class="ln">128</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">129</span><span class="cl"><span class="c1"></span>    <span class="c1">// 指派運算子
</span></span></span><span class="line"><span class="ln">130</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">131</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">132</span><span class="cl">    <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">133</span><span class="cl">    <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">StringProcessor</span><span class="o">&amp;&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">134</span><span class="cl">
</span></span><span class="line"><span class="ln">135</span><span class="cl"><span class="k">private</span><span class="o">:</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">137</span><span class="cl">
</span></span><span class="line"><span class="ln">138</span><span class="cl">    <span class="c1">// 處理計數器（用於展示狀態追蹤）
</span></span></span><span class="line"><span class="ln">139</span><span class="cl"><span class="c1"></span>    <span class="k">mutable</span> <span class="n">size_t</span> <span class="n">operation_count_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">140</span><span class="cl">
</span></span><span class="line"><span class="ln">141</span><span class="cl">    <span class="c1">// 輔助方法
</span></span></span><span class="line"><span class="ln">142</span><span class="cl"><span class="c1"></span>    <span class="kt">void</span> <span class="nf">increment_operation_count</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="o">++</span><span class="n">operation_count_</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">143</span><span class="cl">
</span></span><span class="line"><span class="ln">144</span><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="ln">145</span><span class="cl">    <span class="c1">// 取得操作計數（用於效能分析）
</span></span></span><span class="line"><span class="ln">146</span><span class="cl"><span class="c1"></span>    <span class="n">size_t</span> <span class="n">operation_count</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">operation_count_</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">147</span><span class="cl">    <span class="kt">void</span> <span class="nf">reset_operation_count</span><span class="p">()</span> <span class="p">{</span> <span class="n">operation_count_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">148</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">149</span><span class="cl">
</span></span><span class="line"><span class="ln">150</span><span class="cl"><span class="cp">#endif </span><span class="c1">// STRING_PROCESSOR_HPP
</span></span></span></code></pre></div><h3 id="步驟-3c-實作">步驟 3：C++ 實作</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c1">// src/string_processor.cpp
</span></span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&#34;string_processor.hpp&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;algorithm&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;cctype&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  5</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;sstream&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="c1">// 建構子與解構子
</span></span></span><span class="line"><span class="ln">  9</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 11</span><span class="cl"><span class="n">StringProcessor</span><span class="o">::</span><span class="n">StringProcessor</span><span class="p">()</span> <span class="o">:</span> <span class="n">content_</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">)</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 12</span><span class="cl">
</span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="n">StringProcessor</span><span class="o">::</span><span class="n">StringProcessor</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 14</span><span class="cl">    <span class="o">:</span> <span class="n">content_</span><span class="p">(</span><span class="n">content</span><span class="p">)</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 15</span><span class="cl">
</span></span><span class="line"><span class="ln"> 16</span><span class="cl"><span class="n">StringProcessor</span><span class="o">::</span><span class="n">StringProcessor</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 17</span><span class="cl">    <span class="o">:</span> <span class="n">content_</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">),</span> <span class="n">operation_count_</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 18</span><span class="cl">
</span></span><span class="line"><span class="ln"> 19</span><span class="cl"><span class="n">StringProcessor</span><span class="o">::</span><span class="n">StringProcessor</span><span class="p">(</span><span class="n">StringProcessor</span><span class="o">&amp;&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span>
</span></span><span class="line"><span class="ln"> 20</span><span class="cl">    <span class="o">:</span> <span class="n">content_</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">)),</span> <span class="n">operation_count_</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl">    <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 22</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 23</span><span class="cl">
</span></span><span class="line"><span class="ln"> 24</span><span class="cl"><span class="n">StringProcessor</span><span class="o">::~</span><span class="n">StringProcessor</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">
</span></span><span class="line"><span class="ln"> 26</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 27</span><span class="cl"><span class="c1">// 基本方法
</span></span></span><span class="line"><span class="ln"> 28</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 29</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 30</span><span class="cl"><span class="kt">void</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">set_content</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">content</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 31</span><span class="cl">    <span class="n">content_</span> <span class="o">=</span> <span class="n">content</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 32</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 33</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 34</span><span class="cl">
</span></span><span class="line"><span class="ln"> 35</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 36</span><span class="cl"><span class="c1">// 字串處理方法
</span></span></span><span class="line"><span class="ln"> 37</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 38</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 39</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">to_upper</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 40</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 42</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">transform</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">result</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln"> 43</span><span class="cl">                   <span class="p">[](</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">toupper</span><span class="p">(</span><span class="n">c</span><span class="p">);</span> <span class="p">});</span>
</span></span><span class="line"><span class="ln"> 44</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 46</span><span class="cl">
</span></span><span class="line"><span class="ln"> 47</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">to_lower</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 49</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 50</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">transform</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result</span><span class="p">.</span><span class="n">end</span><span class="p">(),</span> <span class="n">result</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln"> 51</span><span class="cl">                   <span class="p">[](</span><span class="kt">unsigned</span> <span class="kt">char</span> <span class="n">c</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">tolower</span><span class="p">(</span><span class="n">c</span><span class="p">);</span> <span class="p">});</span>
</span></span><span class="line"><span class="ln"> 52</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">
</span></span><span class="line"><span class="ln"> 55</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">reverse</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 56</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 57</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 58</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">reverse</span><span class="p">(</span><span class="n">result</span><span class="p">.</span><span class="n">begin</span><span class="p">(),</span> <span class="n">result</span><span class="p">.</span><span class="n">end</span><span class="p">());</span>
</span></span><span class="line"><span class="ln"> 59</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 60</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">
</span></span><span class="line"><span class="ln"> 62</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">trim</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">    <span class="n">size_t</span> <span class="n">start</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find_first_not_of</span><span class="p">(</span><span class="s">&#34; </span><span class="se">\t\n\r\f\v</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 65</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">start</span> <span class="o">==</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl">        <span class="k">return</span> <span class="s">&#34;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl">    <span class="n">size_t</span> <span class="n">end</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find_last_not_of</span><span class="p">(</span><span class="s">&#34; </span><span class="se">\t\n\r\f\v</span><span class="s">&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 69</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">-</span> <span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 71</span><span class="cl">
</span></span><span class="line"><span class="ln"> 72</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">split</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">delimiter</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">
</span></span><span class="line"><span class="ln"> 76</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">delimiter</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">        <span class="c1">// 空分隔符：按字元分割
</span></span></span><span class="line"><span class="ln"> 78</span><span class="cl"><span class="c1"></span>        <span class="k">for</span> <span class="p">(</span><span class="kt">char</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">content_</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 79</span><span class="cl">            <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="p">));</span>
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 81</span><span class="cl">        <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 82</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 83</span><span class="cl">
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">    <span class="n">size_t</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">    <span class="n">size_t</span> <span class="n">end</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">delimiter</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">    <span class="k">while</span> <span class="p">(</span><span class="n">end</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl">        <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">content_</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="n">start</span><span class="p">,</span> <span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="p">));</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="n">end</span> <span class="o">+</span> <span class="n">delimiter</span><span class="p">.</span><span class="n">length</span><span class="p">();</span>
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">        <span class="n">end</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">delimiter</span><span class="p">,</span> <span class="n">start</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 91</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl">
</span></span><span class="line"><span class="ln"> 93</span><span class="cl">    <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">content_</span><span class="p">.</span><span class="n">substr</span><span class="p">(</span><span class="n">start</span><span class="p">));</span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 96</span><span class="cl">
</span></span><span class="line"><span class="ln"> 97</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">replace</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">old_str</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 98</span><span class="cl">                                     <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">new_str</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">100</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">old_str</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl">        <span class="k">return</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">103</span><span class="cl">
</span></span><span class="line"><span class="ln">104</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">    <span class="n">size_t</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">106</span><span class="cl">    <span class="k">while</span> <span class="p">((</span><span class="n">pos</span> <span class="o">=</span> <span class="n">result</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">old_str</span><span class="p">,</span> <span class="n">pos</span><span class="p">))</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">107</span><span class="cl">        <span class="n">result</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="n">pos</span><span class="p">,</span> <span class="n">old_str</span><span class="p">.</span><span class="n">length</span><span class="p">(),</span> <span class="n">new_str</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">108</span><span class="cl">        <span class="n">pos</span> <span class="o">+=</span> <span class="n">new_str</span><span class="p">.</span><span class="n">length</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">109</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">110</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">111</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">112</span><span class="cl">
</span></span><span class="line"><span class="ln">113</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">114</span><span class="cl"><span class="c1">// 統計分析方法
</span></span></span><span class="line"><span class="ln">115</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">116</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">117</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">char_frequency</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">119</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">unordered_map</span><span class="o">&lt;</span><span class="kt">char</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">freq</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">120</span><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">char</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">content_</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">121</span><span class="cl">        <span class="n">freq</span><span class="p">[</span><span class="n">c</span><span class="p">]</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">122</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">123</span><span class="cl">    <span class="k">return</span> <span class="n">freq</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">124</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">125</span><span class="cl">
</span></span><span class="line"><span class="ln">126</span><span class="cl"><span class="n">size_t</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">word_count</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">127</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">128</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">content_</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">129</span><span class="cl">        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">130</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">131</span><span class="cl">
</span></span><span class="line"><span class="ln">132</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">istringstream</span> <span class="n">iss</span><span class="p">(</span><span class="n">content_</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">133</span><span class="cl">    <span class="n">size_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">134</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">word</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">135</span><span class="cl">    <span class="k">while</span> <span class="p">(</span><span class="n">iss</span> <span class="o">&gt;&gt;</span> <span class="n">word</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">        <span class="n">count</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">137</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">138</span><span class="cl">    <span class="k">return</span> <span class="n">count</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">139</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">140</span><span class="cl">
</span></span><span class="line"><span class="ln">141</span><span class="cl"><span class="n">size_t</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">count_occurrences</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">142</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">143</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">substring</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">144</span><span class="cl">        <span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">145</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">146</span><span class="cl">
</span></span><span class="line"><span class="ln">147</span><span class="cl">    <span class="n">size_t</span> <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">148</span><span class="cl">    <span class="n">size_t</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">149</span><span class="cl">    <span class="k">while</span> <span class="p">((</span><span class="n">pos</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">,</span> <span class="n">pos</span><span class="p">))</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">150</span><span class="cl">        <span class="n">count</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">151</span><span class="cl">        <span class="n">pos</span> <span class="o">+=</span> <span class="n">substring</span><span class="p">.</span><span class="n">length</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">152</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">153</span><span class="cl">    <span class="k">return</span> <span class="n">count</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">154</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">155</span><span class="cl">
</span></span><span class="line"><span class="ln">156</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">157</span><span class="cl"><span class="c1">// 搜尋方法
</span></span></span><span class="line"><span class="ln">158</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">159</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">160</span><span class="cl"><span class="kt">int</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">find</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">,</span> <span class="n">size_t</span> <span class="n">start</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">161</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">162</span><span class="cl">    <span class="n">size_t</span> <span class="n">pos</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">,</span> <span class="n">start</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">163</span><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">pos</span> <span class="o">==</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="o">?</span> <span class="o">-</span><span class="mi">1</span> <span class="o">:</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="n">pos</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">164</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">165</span><span class="cl">
</span></span><span class="line"><span class="ln">166</span><span class="cl"><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">size_t</span><span class="o">&gt;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">find_all</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">167</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">168</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">size_t</span><span class="o">&gt;</span> <span class="n">positions</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">169</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">substring</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">170</span><span class="cl">        <span class="k">return</span> <span class="n">positions</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">171</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">172</span><span class="cl">
</span></span><span class="line"><span class="ln">173</span><span class="cl">    <span class="n">size_t</span> <span class="n">pos</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">174</span><span class="cl">    <span class="k">while</span> <span class="p">((</span><span class="n">pos</span> <span class="o">=</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">,</span> <span class="n">pos</span><span class="p">))</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">175</span><span class="cl">        <span class="n">positions</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">pos</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">176</span><span class="cl">        <span class="n">pos</span> <span class="o">+=</span> <span class="n">substring</span><span class="p">.</span><span class="n">length</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">177</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">178</span><span class="cl">    <span class="k">return</span> <span class="n">positions</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">179</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">180</span><span class="cl">
</span></span><span class="line"><span class="ln">181</span><span class="cl"><span class="kt">bool</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">contains</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">substring</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">182</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">183</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">)</span> <span class="o">!=</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">::</span><span class="n">npos</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">184</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">185</span><span class="cl">
</span></span><span class="line"><span class="ln">186</span><span class="cl"><span class="kt">bool</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">starts_with</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">prefix</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">187</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">188</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">prefix</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">content_</span><span class="p">.</span><span class="n">length</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">189</span><span class="cl">        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">190</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">191</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">compare</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">prefix</span><span class="p">.</span><span class="n">length</span><span class="p">(),</span> <span class="n">prefix</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">192</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">193</span><span class="cl">
</span></span><span class="line"><span class="ln">194</span><span class="cl"><span class="kt">bool</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="n">ends_with</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">suffix</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">195</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">196</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">suffix</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">&gt;</span> <span class="n">content_</span><span class="p">.</span><span class="n">length</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">197</span><span class="cl">        <span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">198</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">199</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span><span class="p">.</span><span class="n">compare</span><span class="p">(</span><span class="n">content_</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">-</span> <span class="n">suffix</span><span class="p">.</span><span class="n">length</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">200</span><span class="cl">                            <span class="n">suffix</span><span class="p">.</span><span class="n">length</span><span class="p">(),</span> <span class="n">suffix</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">201</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">202</span><span class="cl">
</span></span><span class="line"><span class="ln">203</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">204</span><span class="cl"><span class="c1">// 運算子重載
</span></span></span><span class="line"><span class="ln">205</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">206</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">207</span><span class="cl"><span class="n">StringProcessor</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">208</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">209</span><span class="cl">    <span class="k">return</span> <span class="nf">StringProcessor</span><span class="p">(</span><span class="n">content_</span> <span class="o">+</span> <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">210</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">211</span><span class="cl">
</span></span><span class="line"><span class="ln">212</span><span class="cl"><span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">+=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">213</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">214</span><span class="cl">    <span class="n">content_</span> <span class="o">+=</span> <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">215</span><span class="cl">    <span class="k">return</span> <span class="o">*</span><span class="k">this</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">216</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">217</span><span class="cl">
</span></span><span class="line"><span class="ln">218</span><span class="cl"><span class="kt">char</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="p">[](</span><span class="n">size_t</span> <span class="n">index</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">219</span><span class="cl">    <span class="n">increment_operation_count</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">220</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">index</span> <span class="o">&gt;=</span> <span class="n">content_</span><span class="p">.</span><span class="n">length</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">221</span><span class="cl">        <span class="k">throw</span> <span class="n">std</span><span class="o">::</span><span class="n">out_of_range</span><span class="p">(</span><span class="s">&#34;Index out of range: &#34;</span> <span class="o">+</span> <span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">index</span><span class="p">));</span>
</span></span><span class="line"><span class="ln">222</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">223</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span><span class="p">[</span><span class="n">index</span><span class="p">];</span>
</span></span><span class="line"><span class="ln">224</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">225</span><span class="cl">
</span></span><span class="line"><span class="ln">226</span><span class="cl"><span class="kt">bool</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">==</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">227</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span> <span class="o">==</span> <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">228</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">229</span><span class="cl">
</span></span><span class="line"><span class="ln">230</span><span class="cl"><span class="kt">bool</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">!=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">231</span><span class="cl">    <span class="k">return</span> <span class="n">content_</span> <span class="o">!=</span> <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">232</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">233</span><span class="cl">
</span></span><span class="line"><span class="ln">234</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">235</span><span class="cl"><span class="c1">// 指派運算子
</span></span></span><span class="line"><span class="ln">236</span><span class="cl"><span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">237</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">238</span><span class="cl"><span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">239</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="k">this</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">other</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">240</span><span class="cl">        <span class="n">content_</span> <span class="o">=</span> <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">241</span><span class="cl">        <span class="n">operation_count_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">242</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">243</span><span class="cl">    <span class="k">return</span> <span class="o">*</span><span class="k">this</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">244</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">245</span><span class="cl">
</span></span><span class="line"><span class="ln">246</span><span class="cl"><span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="o">=</span><span class="p">(</span><span class="n">StringProcessor</span><span class="o">&amp;&amp;</span> <span class="n">other</span><span class="p">)</span> <span class="k">noexcept</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">247</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="k">this</span> <span class="o">!=</span> <span class="o">&amp;</span><span class="n">other</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">248</span><span class="cl">        <span class="n">content_</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">move</span><span class="p">(</span><span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">249</span><span class="cl">        <span class="n">operation_count_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">250</span><span class="cl">        <span class="n">other</span><span class="p">.</span><span class="n">content_</span><span class="p">.</span><span class="n">clear</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">251</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">252</span><span class="cl">    <span class="k">return</span> <span class="o">*</span><span class="k">this</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">253</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h3 id="步驟-4pybind11-綁定">步驟 4：pybind11 綁定</h3>
<p>這是最關鍵的部分，將 C++ 類別暴露給 Python：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c1">// src/bindings.cpp
</span></span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&lt;pybind11/pybind11.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;pybind11/stl.h&gt;</span><span class="cp">  </span><span class="c1">// 支援 STL 容器自動轉換
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&lt;pybind11/operators.h&gt;</span><span class="cp">  </span><span class="c1">// 支援運算子重載
</span></span></span><span class="line"><span class="ln">  5</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&#34;string_processor.hpp&#34;</span><span class="cp">
</span></span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="k">namespace</span> <span class="n">py</span> <span class="o">=</span> <span class="n">pybind11</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">  9</span><span class="cl">
</span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="n">PYBIND11_MODULE</span><span class="p">(</span><span class="n">string_processor</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 11</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">doc</span><span class="p">()</span> <span class="o">=</span> <span class="s">&#34;StringProcessor: 高效能字串處理模組&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 12</span><span class="cl">
</span></span><span class="line"><span class="ln"> 13</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 14</span><span class="cl"><span class="c1"></span>    <span class="c1">// 類別綁定
</span></span></span><span class="line"><span class="ln"> 15</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln"> 16</span><span class="cl"><span class="c1"></span>    <span class="n">py</span><span class="o">::</span><span class="n">class_</span><span class="o">&lt;</span><span class="n">StringProcessor</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="s">&#34;StringProcessor&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 17</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 18</span><span class="cl"><span class="c1"></span>        <span class="c1">// 建構子
</span></span></span><span class="line"><span class="ln"> 19</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 20</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">init</span><span class="o">&lt;&gt;</span><span class="p">(),</span> <span class="s">&#34;建立空的 StringProcessor&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">init</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;&gt;</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln"> 22</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;content&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 23</span><span class="cl">             <span class="s">&#34;使用指定內容建立 StringProcessor&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 24</span><span class="cl">
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">        <span class="c1">// 複製建構（Python 的 copy 模組會使用）
</span></span></span><span class="line"><span class="ln"> 26</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">init</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;&gt;</span><span class="p">())</span>
</span></span><span class="line"><span class="ln"> 27</span><span class="cl">
</span></span><span class="line"><span class="ln"> 28</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 29</span><span class="cl"><span class="c1"></span>        <span class="c1">// 屬性
</span></span></span><span class="line"><span class="ln"> 30</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 31</span><span class="cl"><span class="c1"></span>        <span class="c1">// content 屬性：可讀寫
</span></span></span><span class="line"><span class="ln"> 32</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def_property</span><span class="p">(</span><span class="s">&#34;content&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 33</span><span class="cl">                      <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">content</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 34</span><span class="cl">                      <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">set_content</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 35</span><span class="cl">                      <span class="s">&#34;字串內容&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 36</span><span class="cl">
</span></span><span class="line"><span class="ln"> 37</span><span class="cl">        <span class="c1">// 唯讀屬性
</span></span></span><span class="line"><span class="ln"> 38</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def_property_readonly</span><span class="p">(</span><span class="s">&#34;length&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 39</span><span class="cl">                               <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">length</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 40</span><span class="cl">                               <span class="s">&#34;字串長度&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">        <span class="p">.</span><span class="n">def_property_readonly</span><span class="p">(</span><span class="s">&#34;empty&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 42</span><span class="cl">                               <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">empty</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 43</span><span class="cl">                               <span class="s">&#34;是否為空&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 44</span><span class="cl">        <span class="p">.</span><span class="n">def_property_readonly</span><span class="p">(</span><span class="s">&#34;operation_count&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">                               <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">operation_count</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 46</span><span class="cl">                               <span class="s">&#34;操作計數器&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 47</span><span class="cl">
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 49</span><span class="cl"><span class="c1"></span>        <span class="c1">// 基本方法
</span></span></span><span class="line"><span class="ln"> 50</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 51</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;reset_operation_count&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 52</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">reset_operation_count</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl">             <span class="s">&#34;重置操作計數器&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">
</span></span><span class="line"><span class="ln"> 55</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 56</span><span class="cl"><span class="c1"></span>        <span class="c1">// 字串處理方法
</span></span></span><span class="line"><span class="ln"> 57</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 58</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;to_upper&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 59</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">to_upper</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 60</span><span class="cl">             <span class="s">&#34;轉換為大寫&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;to_lower&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 62</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">to_lower</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">             <span class="s">&#34;轉換為小寫&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;reverse&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 65</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">reverse</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl">             <span class="s">&#34;反轉字串&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;trim&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">trim</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 69</span><span class="cl">             <span class="s">&#34;移除前後空白&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;split&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 71</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">split</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 72</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;delimiter&#34;</span><span class="p">)</span> <span class="o">=</span> <span class="s">&#34; &#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">             <span class="s">&#34;以分隔符分割字串&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;replace&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">replace</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 76</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;old_str&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;new_str&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 78</span><span class="cl">             <span class="s">&#34;取代子字串&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 79</span><span class="cl">
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 81</span><span class="cl"><span class="c1"></span>        <span class="c1">// 統計分析方法
</span></span></span><span class="line"><span class="ln"> 82</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 83</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;char_frequency&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">char_frequency</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">             <span class="s">&#34;統計字元頻率&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;word_count&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">word_count</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl">             <span class="s">&#34;計算單字數量&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;count_occurrences&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">count_occurrences</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 91</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;substring&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl">             <span class="s">&#34;計算子字串出現次數&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 93</span><span class="cl">
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="c1"></span>        <span class="c1">// 搜尋方法
</span></span></span><span class="line"><span class="ln"> 96</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln"> 97</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;find&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 98</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">find</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;substring&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">100</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;start&#34;</span><span class="p">)</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl">             <span class="s">&#34;搜尋子字串位置（找不到回傳 -1）&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;find_all&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">103</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">find_all</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">104</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;substring&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">             <span class="s">&#34;搜尋所有出現位置&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">106</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;contains&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">107</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">contains</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">108</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;substring&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">109</span><span class="cl">             <span class="s">&#34;是否包含子字串&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">110</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;starts_with&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">111</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">starts_with</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">112</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;prefix&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">113</span><span class="cl">             <span class="s">&#34;是否以指定字串開頭&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">114</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;ends_with&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">115</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">ends_with</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">116</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;suffix&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">117</span><span class="cl">             <span class="s">&#34;是否以指定字串結尾&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">
</span></span><span class="line"><span class="ln">119</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln">120</span><span class="cl"><span class="c1"></span>        <span class="c1">// 運算子重載
</span></span></span><span class="line"><span class="ln">121</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln">122</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">123</span><span class="cl">        <span class="c1">// + 運算子：StringProcessor + StringProcessor
</span></span></span><span class="line"><span class="ln">124</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">self</span> <span class="o">+</span> <span class="n">py</span><span class="o">::</span><span class="n">self</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">125</span><span class="cl">
</span></span><span class="line"><span class="ln">126</span><span class="cl">        <span class="c1">// += 運算子
</span></span></span><span class="line"><span class="ln">127</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">self</span> <span class="o">+=</span> <span class="n">py</span><span class="o">::</span><span class="n">self</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">128</span><span class="cl">
</span></span><span class="line"><span class="ln">129</span><span class="cl">        <span class="c1">// == 和 != 運算子
</span></span></span><span class="line"><span class="ln">130</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">self</span> <span class="o">==</span> <span class="n">py</span><span class="o">::</span><span class="n">self</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">131</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">self</span> <span class="o">!=</span> <span class="n">py</span><span class="o">::</span><span class="n">self</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">132</span><span class="cl">
</span></span><span class="line"><span class="ln">133</span><span class="cl">        <span class="c1">// [] 運算子：索引存取
</span></span></span><span class="line"><span class="ln">134</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__getitem__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">135</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="k">operator</span><span class="p">[],</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;index&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">137</span><span class="cl">             <span class="s">&#34;取得指定位置的字元&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">138</span><span class="cl">
</span></span><span class="line"><span class="ln">139</span><span class="cl">        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln">140</span><span class="cl"><span class="c1"></span>        <span class="c1">// Python 特殊方法
</span></span></span><span class="line"><span class="ln">141</span><span class="cl"><span class="c1"></span>        <span class="c1">// ----------------------------------------
</span></span></span><span class="line"><span class="ln">142</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">143</span><span class="cl">        <span class="c1">// __repr__：物件表示
</span></span></span><span class="line"><span class="ln">144</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__repr__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">145</span><span class="cl">             <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">146</span><span class="cl">                 <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">repr</span> <span class="o">=</span> <span class="s">&#34;&lt;StringProcessor content=&#39;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">147</span><span class="cl">                 <span class="k">if</span> <span class="p">(</span><span class="n">sp</span><span class="p">.</span><span class="n">length</span><span class="p">()</span> <span class="o">&gt;</span> <span class="mi">50</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">148</span><span class="cl">                     <span class="n">repr</span> <span class="o">+=</span> <span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">().</span><span class="n">substr</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">47</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#34;...&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">149</span><span class="cl">                 <span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">150</span><span class="cl">                     <span class="n">repr</span> <span class="o">+=</span> <span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">151</span><span class="cl">                 <span class="p">}</span>
</span></span><span class="line"><span class="ln">152</span><span class="cl">                 <span class="n">repr</span> <span class="o">+=</span> <span class="s">&#34;&#39; length=&#34;</span> <span class="o">+</span> <span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">sp</span><span class="p">.</span><span class="n">length</span><span class="p">())</span> <span class="o">+</span> <span class="s">&#34;&gt;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">153</span><span class="cl">                 <span class="k">return</span> <span class="n">repr</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">154</span><span class="cl">             <span class="p">})</span>
</span></span><span class="line"><span class="ln">155</span><span class="cl">
</span></span><span class="line"><span class="ln">156</span><span class="cl">        <span class="c1">// __str__：字串轉換
</span></span></span><span class="line"><span class="ln">157</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__str__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">158</span><span class="cl">             <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">159</span><span class="cl">                 <span class="k">return</span> <span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">160</span><span class="cl">             <span class="p">})</span>
</span></span><span class="line"><span class="ln">161</span><span class="cl">
</span></span><span class="line"><span class="ln">162</span><span class="cl">        <span class="c1">// __len__：長度
</span></span></span><span class="line"><span class="ln">163</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__len__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">164</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">length</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">165</span><span class="cl">
</span></span><span class="line"><span class="ln">166</span><span class="cl">        <span class="c1">// __bool__：布林轉換
</span></span></span><span class="line"><span class="ln">167</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__bool__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">168</span><span class="cl">             <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">169</span><span class="cl">                 <span class="k">return</span> <span class="o">!</span><span class="n">sp</span><span class="p">.</span><span class="n">empty</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">170</span><span class="cl">             <span class="p">})</span>
</span></span><span class="line"><span class="ln">171</span><span class="cl">
</span></span><span class="line"><span class="ln">172</span><span class="cl">        <span class="c1">// __contains__：in 運算子
</span></span></span><span class="line"><span class="ln">173</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__contains__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">174</span><span class="cl">             <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">contains</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">175</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;substring&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">176</span><span class="cl">
</span></span><span class="line"><span class="ln">177</span><span class="cl">        <span class="c1">// __iter__：迭代支援
</span></span></span><span class="line"><span class="ln">178</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__iter__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">179</span><span class="cl">             <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">180</span><span class="cl">                 <span class="k">return</span> <span class="n">py</span><span class="o">::</span><span class="n">make_iterator</span><span class="p">(</span><span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">().</span><span class="n">begin</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">181</span><span class="cl">                                          <span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">().</span><span class="n">end</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">182</span><span class="cl">             <span class="p">},</span>
</span></span><span class="line"><span class="ln">183</span><span class="cl">             <span class="n">py</span><span class="o">::</span><span class="n">keep_alive</span><span class="o">&lt;</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="o">&gt;</span><span class="p">())</span>  <span class="c1">// 保持物件存活
</span></span></span><span class="line"><span class="ln">184</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">185</span><span class="cl">        <span class="c1">// __hash__：雜湊支援（讓物件可作為 dict key）
</span></span></span><span class="line"><span class="ln">186</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__hash__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">187</span><span class="cl">             <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">188</span><span class="cl">                 <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">hash</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span><span class="p">{}(</span><span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">189</span><span class="cl">             <span class="p">})</span>
</span></span><span class="line"><span class="ln">190</span><span class="cl">
</span></span><span class="line"><span class="ln">191</span><span class="cl">        <span class="c1">// 支援 pickle
</span></span></span><span class="line"><span class="ln">192</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">pickle</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">193</span><span class="cl">            <span class="c1">// __getstate__
</span></span></span><span class="line"><span class="ln">194</span><span class="cl"><span class="c1"></span>            <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">195</span><span class="cl">                <span class="k">return</span> <span class="n">py</span><span class="o">::</span><span class="n">make_tuple</span><span class="p">(</span><span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">196</span><span class="cl">            <span class="p">},</span>
</span></span><span class="line"><span class="ln">197</span><span class="cl">            <span class="c1">// __setstate__
</span></span></span><span class="line"><span class="ln">198</span><span class="cl"><span class="c1"></span>            <span class="p">[](</span><span class="n">py</span><span class="o">::</span><span class="n">tuple</span> <span class="n">t</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">199</span><span class="cl">                <span class="k">if</span> <span class="p">(</span><span class="n">t</span><span class="p">.</span><span class="n">size</span><span class="p">()</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">200</span><span class="cl">                    <span class="k">throw</span> <span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="p">(</span><span class="s">&#34;Invalid state&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">201</span><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="ln">202</span><span class="cl">                <span class="k">return</span> <span class="nf">StringProcessor</span><span class="p">(</span><span class="n">t</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">cast</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&gt;</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">203</span><span class="cl">            <span class="p">}</span>
</span></span><span class="line"><span class="ln">204</span><span class="cl">        <span class="p">));</span>
</span></span><span class="line"><span class="ln">205</span><span class="cl">
</span></span><span class="line"><span class="ln">206</span><span class="cl">    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">207</span><span class="cl"><span class="c1"></span>    <span class="c1">// 模組層級函式
</span></span></span><span class="line"><span class="ln">208</span><span class="cl"><span class="c1"></span>    <span class="c1">// ========================================
</span></span></span><span class="line"><span class="ln">209</span><span class="cl"><span class="c1"></span>    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;concatenate&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">210</span><span class="cl">          <span class="p">[](</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">StringProcessor</span><span class="o">&gt;&amp;</span> <span class="n">processors</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">211</span><span class="cl">             <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">separator</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">212</span><span class="cl">              <span class="k">if</span> <span class="p">(</span><span class="n">processors</span><span class="p">.</span><span class="n">empty</span><span class="p">())</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">213</span><span class="cl">                  <span class="k">return</span> <span class="nf">StringProcessor</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">214</span><span class="cl">              <span class="p">}</span>
</span></span><span class="line"><span class="ln">215</span><span class="cl">              <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">result</span> <span class="o">=</span> <span class="n">processors</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">content</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">216</span><span class="cl">              <span class="k">for</span> <span class="p">(</span><span class="n">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">processors</span><span class="p">.</span><span class="n">size</span><span class="p">();</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">217</span><span class="cl">                  <span class="n">result</span> <span class="o">+=</span> <span class="n">separator</span> <span class="o">+</span> <span class="n">processors</span><span class="p">[</span><span class="n">i</span><span class="p">].</span><span class="n">content</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">218</span><span class="cl">              <span class="p">}</span>
</span></span><span class="line"><span class="ln">219</span><span class="cl">              <span class="k">return</span> <span class="nf">StringProcessor</span><span class="p">(</span><span class="n">result</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">220</span><span class="cl">          <span class="p">},</span>
</span></span><span class="line"><span class="ln">221</span><span class="cl">          <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;processors&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="ln">222</span><span class="cl">          <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;separator&#34;</span><span class="p">)</span> <span class="o">=</span> <span class="s">&#34;&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">223</span><span class="cl">          <span class="s">&#34;串接多個 StringProcessor&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">224</span><span class="cl">
</span></span><span class="line"><span class="ln">225</span><span class="cl">    <span class="c1">// 版本資訊
</span></span></span><span class="line"><span class="ln">226</span><span class="cl"><span class="c1"></span>    <span class="n">m</span><span class="p">.</span><span class="n">attr</span><span class="p">(</span><span class="s">&#34;__version__&#34;</span><span class="p">)</span> <span class="o">=</span> <span class="s">&#34;0.1.0&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">227</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h3 id="步驟-5建構檔案">步驟 5：建構檔案</h3>
<p><strong>CMakeLists.txt</strong>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="nb">cmake_minimum_required</span><span class="p">(</span><span class="s">VERSION</span> <span class="s">3.15</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="err"></span><span class="nb">project</span><span class="p">(</span><span class="s">string_processor</span> <span class="s">LANGUAGES</span> <span class="s">CXX</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="err"></span><span class="nb">set</span><span class="p">(</span><span class="s">CMAKE_CXX_STANDARD</span> <span class="s">17</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="err"></span><span class="nb">set</span><span class="p">(</span><span class="s">CMAKE_CXX_STANDARD_REQUIRED</span> <span class="s">ON</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="err"></span><span class="c"># 找到 pybind11
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c"></span><span class="nb">find_package</span><span class="p">(</span><span class="s">pybind11</span> <span class="s">REQUIRED</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="err"></span><span class="c"># 建立 Python 模組
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c"></span><span class="nb">pybind11_add_module</span><span class="p">(</span><span class="s">string_processor</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="s">src/string_processor.cpp</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="s">src/bindings.cpp</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="err"></span><span class="c"># 包含標頭檔目錄
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c"></span><span class="nb">target_include_directories</span><span class="p">(</span><span class="s">string_processor</span> <span class="s">PRIVATE</span> <span class="s">src</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="err"></span><span class="c"># 優化設定
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c"></span><span class="nb">target_compile_options</span><span class="p">(</span><span class="s">string_processor</span> <span class="s">PRIVATE</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="o">$&lt;</span><span class="nv">$&lt;CXX_COMPILER_ID:GNU,Clang</span><span class="o">&gt;</span><span class="s">:-O3</span> <span class="s">-march=native&gt;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="o">$&lt;</span><span class="nv">$&lt;CXX_COMPILER_ID:MSVC</span><span class="o">&gt;</span><span class="s">:/O2&gt;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><p><strong>setup.py</strong>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># setup.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">from</span> <span class="nn">setuptools</span> <span class="kn">import</span> <span class="n">setup</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">from</span> <span class="nn">pybind11.setup_helpers</span> <span class="kn">import</span> <span class="n">Pybind11Extension</span><span class="p">,</span> <span class="n">build_ext</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">ext_modules</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">Pybind11Extension</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="s2">&#34;string_processor&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="n">sources</span><span class="o">=</span><span class="p">[</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">            <span class="s2">&#34;src/string_processor.cpp&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">            <span class="s2">&#34;src/bindings.cpp&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">        <span class="p">],</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="n">include_dirs</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;src&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="n">cxx_std</span><span class="o">=</span><span class="mi">17</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="n">extra_compile_args</span><span class="o">=</span><span class="p">[</span><span class="s2">&#34;-O3&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="p">),</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="n">setup</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="n">name</span><span class="o">=</span><span class="s2">&#34;string_processor&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">version</span><span class="o">=</span><span class="s2">&#34;0.1.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="n">description</span><span class="o">=</span><span class="s2">&#34;High-performance string processor using pybind11&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="n">ext_modules</span><span class="o">=</span><span class="n">ext_modules</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="n">cmdclass</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;build_ext&#34;</span><span class="p">:</span> <span class="n">build_ext</span><span class="p">},</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="n">python_requires</span><span class="o">=</span><span class="s2">&#34;&gt;=3.8&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><h2 id="記憶體管理與物件生命週期">記憶體管理與物件生命週期</h2>
<h3 id="pybind11-的記憶體管理策略">pybind11 的記憶體管理策略</h3>
<p>pybind11 提供多種方式控制物件的所有權：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// 1. return_value_policy::automatic（預設）
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1">// pybind11 自動決定最佳策略
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"></span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;get_content&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1">// 2. return_value_policy::copy
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1">// 總是建立副本，Python 擁有副本
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"></span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;get_content_copy&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">content</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">     <span class="n">py</span><span class="o">::</span><span class="n">return_value_policy</span><span class="o">::</span><span class="n">copy</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1">// 3. return_value_policy::reference
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1">// 回傳參考，不轉移所有權（危險：可能產生懸空指標）
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"></span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;get_content_ref&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">content</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">     <span class="n">py</span><span class="o">::</span><span class="n">return_value_policy</span><span class="o">::</span><span class="n">reference</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="c1">// 4. return_value_policy::reference_internal
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1">// 回傳參考，並保持父物件存活
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"></span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;get_content_internal&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">StringProcessor</span><span class="o">::</span><span class="n">content</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">     <span class="n">py</span><span class="o">::</span><span class="n">return_value_policy</span><span class="o">::</span><span class="n">reference_internal</span><span class="p">)</span></span></span></code></pre></div><h3 id="keep_alive-策略">keep_alive 策略</h3>
<p>當物件間有依賴關係時，使用 <code>keep_alive</code> 確保生命週期正確：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// keep_alive&lt;Nurse, Patient&gt;
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1">// Nurse: 需要被保持存活的物件的引數索引
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1">// Patient: 依賴 Nurse 的物件的引數索引
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1">// 0 = 回傳值, 1 = self, 2+ = 其他引數
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1">// 範例：迭代器需要保持原物件存活
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"></span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__iter__&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">     <span class="p">[](</span><span class="k">const</span> <span class="n">StringProcessor</span><span class="o">&amp;</span> <span class="n">sp</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">         <span class="k">return</span> <span class="n">py</span><span class="o">::</span><span class="n">make_iterator</span><span class="p">(</span><span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">().</span><span class="n">begin</span><span class="p">(),</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">                                  <span class="n">sp</span><span class="p">.</span><span class="n">content</span><span class="p">().</span><span class="n">end</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">     <span class="p">},</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">     <span class="n">py</span><span class="o">::</span><span class="n">keep_alive</span><span class="o">&lt;</span><span class="mi">0</span><span class="p">,</span> <span class="mi">1</span><span class="o">&gt;</span><span class="p">())</span>  <span class="c1">// 回傳值(0)存活期間，self(1)必須存活
</span></span></span></code></pre></div><h3 id="智慧指標支援">智慧指標支援</h3>
<p>pybind11 自動支援 <code>std::shared_ptr</code> 和 <code>std::unique_ptr</code>：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1">// 使用 shared_ptr 管理物件
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c1"></span><span class="n">py</span><span class="o">::</span><span class="n">class_</span><span class="o">&lt;</span><span class="n">StringProcessor</span><span class="p">,</span> <span class="n">std</span><span class="o">::</span><span class="n">shared_ptr</span><span class="o">&lt;</span><span class="n">StringProcessor</span><span class="o">&gt;&gt;</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="s">&#34;StringProcessor&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="c1">// ...
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c1">// 工廠函式回傳 shared_ptr
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="c1"></span><span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;create_processor&#34;</span><span class="p">,</span> <span class="p">[]()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">    <span class="k">return</span> <span class="n">std</span><span class="o">::</span><span class="n">make_shared</span><span class="o">&lt;</span><span class="n">StringProcessor</span><span class="o">&gt;</span><span class="p">(</span><span class="s">&#34;factory created&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="p">});</span></span></span></code></pre></div><h2 id="python-使用範例">Python 使用範例</h2>
<h3 id="基本使用">基本使用</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">from</span> <span class="nn">string_processor</span> <span class="kn">import</span> <span class="n">StringProcessor</span><span class="p">,</span> <span class="n">concatenate</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 建立物件</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;Hello, World!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="p">)</span>           <span class="c1"># Hello, World!</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="nb">repr</span><span class="p">(</span><span class="n">sp</span><span class="p">))</span>     <span class="c1"># &lt;StringProcessor content=&#39;Hello, World!&#39; length=13&gt;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="nb">len</span><span class="p">(</span><span class="n">sp</span><span class="p">))</span>      <span class="c1"># 13</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1"># 屬性存取</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>   <span class="c1"># Hello, World!</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">length</span><span class="p">)</span>    <span class="c1"># 13</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">empty</span><span class="p">)</span>     <span class="c1"># False</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="c1"># 修改內容</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">sp</span><span class="o">.</span><span class="n">content</span> <span class="o">=</span> <span class="s2">&#34;New content&#34;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>   <span class="c1"># New content</span></span></span></code></pre></div><h3 id="字串處理">字串處理</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;  Hello, Python World!  &#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 大小寫轉換</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">to_upper</span><span class="p">())</span>  <span class="c1"># &#34;  HELLO, PYTHON WORLD!  &#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">to_lower</span><span class="p">())</span>  <span class="c1"># &#34;  hello, python world!  &#34;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 修剪空白</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">trim</span><span class="p">())</span>      <span class="c1"># &#34;Hello, Python World!&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 反轉</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">reverse</span><span class="p">())</span>   <span class="c1"># &#34;  !dlroW nohtyP ,olleH  &#34;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># 分割</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;apple,banana,cherry&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s2">&#34;,&#34;</span><span class="p">))</span>  <span class="c1"># [&#39;apple&#39;, &#39;banana&#39;, &#39;cherry&#39;]</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"># 取代</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">replace</span><span class="p">(</span><span class="s2">&#34;,&#34;</span><span class="p">,</span> <span class="s2">&#34; | &#34;</span><span class="p">))</span>  <span class="c1"># &#34;apple | banana | cherry&#34;</span></span></span></code></pre></div><h3 id="統計與搜尋">統計與搜尋</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;hello hello world&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 統計</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">word_count</span><span class="p">())</span>              <span class="c1"># 3</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">count_occurrences</span><span class="p">(</span><span class="s2">&#34;hello&#34;</span><span class="p">))</span> <span class="c1"># 2</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">char_frequency</span><span class="p">())</span>          <span class="c1"># {&#39;h&#39;: 2, &#39;e&#39;: 2, &#39;l&#39;: 5, ...}</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># 搜尋</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="s2">&#34;world&#34;</span><span class="p">))</span>             <span class="c1"># 12</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">find_all</span><span class="p">(</span><span class="s2">&#34;hello&#34;</span><span class="p">))</span>         <span class="c1"># [0, 6]</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">contains</span><span class="p">(</span><span class="s2">&#34;world&#34;</span><span class="p">))</span>         <span class="c1"># True</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">starts_with</span><span class="p">(</span><span class="s2">&#34;hello&#34;</span><span class="p">))</span>      <span class="c1"># True</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp</span><span class="o">.</span><span class="n">ends_with</span><span class="p">(</span><span class="s2">&#34;world&#34;</span><span class="p">))</span>        <span class="c1"># True</span></span></span></code></pre></div><h3 id="運算子使用">運算子使用</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="n">sp1</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;Hello&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="n">sp2</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34; World&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># + 運算子</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">sp3</span> <span class="o">=</span> <span class="n">sp1</span> <span class="o">+</span> <span class="n">sp2</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp3</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>   <span class="c1"># &#34;Hello World&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># += 運算子</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="n">sp1</span> <span class="o">+=</span> <span class="n">sp2</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp1</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>   <span class="c1"># &#34;Hello World&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"># [] 索引</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp3</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>        <span class="c1"># &#39;H&#39;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp3</span><span class="p">[</span><span class="mi">6</span><span class="p">])</span>        <span class="c1"># &#39;W&#39;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1"># in 運算子</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="s2">&#34;World&#34;</span> <span class="ow">in</span> <span class="n">sp3</span><span class="p">)</span>  <span class="c1"># True</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1"># 比較運算子</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp1</span> <span class="o">==</span> <span class="n">sp3</span><span class="p">)</span>    <span class="c1"># True</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp1</span> <span class="o">!=</span> <span class="n">sp2</span><span class="p">)</span>    <span class="c1"># True</span></span></span></code></pre></div><h3 id="python-特殊功能">Python 特殊功能</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">copy</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">pickle</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="n">sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="s2">&#34;test data&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1"># 迭代</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="k">for</span> <span class="n">char</span> <span class="ow">in</span> <span class="n">sp</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="n">char</span><span class="p">,</span> <span class="n">end</span><span class="o">=</span><span class="s2">&#34;&#34;</span><span class="p">)</span>  <span class="c1"># t e s t   d a t a</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"># 複製</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="n">sp_copy</span> <span class="o">=</span> <span class="n">copy</span><span class="o">.</span><span class="n">copy</span><span class="p">(</span><span class="n">sp</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="c1"># 序列化</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="n">data</span> <span class="o">=</span> <span class="n">pickle</span><span class="o">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">sp</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="n">sp_restored</span> <span class="o">=</span> <span class="n">pickle</span><span class="o">.</span><span class="n">loads</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">sp_restored</span><span class="o">.</span><span class="n">content</span><span class="p">)</span>  <span class="c1"># &#34;test data&#34;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c1"># 作為 dict key</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="n">cache</span> <span class="o">=</span> <span class="p">{</span><span class="n">sp</span><span class="p">:</span> <span class="s2">&#34;cached value&#34;</span><span class="p">}</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">cache</span><span class="p">[</span><span class="n">sp</span><span class="p">])</span>  <span class="c1"># &#34;cached value&#34;</span></span></span></code></pre></div><h2 id="效能測試">效能測試</h2>
<p>建立效能測試腳本，比較 C++ 綁定與純 Python 實作：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">  1</span><span class="cl"><span class="c1"># benchmark.py</span>
</span></span><span class="line"><span class="ln">  2</span><span class="cl"><span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln">  3</span><span class="cl"><span class="s2">效能比較：pybind11 StringProcessor vs 純 Python
</span></span></span><span class="line"><span class="ln">  4</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">  5</span><span class="cl">
</span></span><span class="line"><span class="ln">  6</span><span class="cl"><span class="kn">import</span> <span class="nn">time</span>
</span></span><span class="line"><span class="ln">  7</span><span class="cl"><span class="kn">import</span> <span class="nn">statistics</span>
</span></span><span class="line"><span class="ln">  8</span><span class="cl"><span class="kn">from</span> <span class="nn">typing</span> <span class="kn">import</span> <span class="n">Callable</span><span class="p">,</span> <span class="n">Any</span>
</span></span><span class="line"><span class="ln">  9</span><span class="cl">
</span></span><span class="line"><span class="ln"> 10</span><span class="cl"><span class="c1"># pybind11 版本</span>
</span></span><span class="line"><span class="ln"> 11</span><span class="cl"><span class="kn">from</span> <span class="nn">string_processor</span> <span class="kn">import</span> <span class="n">StringProcessor</span>
</span></span><span class="line"><span class="ln"> 12</span><span class="cl">
</span></span><span class="line"><span class="ln"> 13</span><span class="cl"><span class="c1"># 純 Python 版本</span>
</span></span><span class="line"><span class="ln"> 14</span><span class="cl"><span class="k">class</span> <span class="nc">PyStringProcessor</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 15</span><span class="cl">    <span class="s2">&#34;&#34;&#34;純 Python 實作作為效能基準&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 16</span><span class="cl">
</span></span><span class="line"><span class="ln"> 17</span><span class="cl">    <span class="k">def</span> <span class="fm">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">content</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">&#34;&#34;</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 18</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_content</span> <span class="o">=</span> <span class="n">content</span>
</span></span><span class="line"><span class="ln"> 19</span><span class="cl">
</span></span><span class="line"><span class="ln"> 20</span><span class="cl">    <span class="nd">@property</span>
</span></span><span class="line"><span class="ln"> 21</span><span class="cl">    <span class="k">def</span> <span class="nf">content</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 22</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span>
</span></span><span class="line"><span class="ln"> 23</span><span class="cl">
</span></span><span class="line"><span class="ln"> 24</span><span class="cl">    <span class="nd">@content.setter</span>
</span></span><span class="line"><span class="ln"> 25</span><span class="cl">    <span class="k">def</span> <span class="nf">content</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">:</span> <span class="nb">str</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 26</span><span class="cl">        <span class="bp">self</span><span class="o">.</span><span class="n">_content</span> <span class="o">=</span> <span class="n">value</span>
</span></span><span class="line"><span class="ln"> 27</span><span class="cl">
</span></span><span class="line"><span class="ln"> 28</span><span class="cl">    <span class="k">def</span> <span class="nf">to_upper</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 29</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 30</span><span class="cl">
</span></span><span class="line"><span class="ln"> 31</span><span class="cl">    <span class="k">def</span> <span class="nf">to_lower</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 32</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">lower</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 33</span><span class="cl">
</span></span><span class="line"><span class="ln"> 34</span><span class="cl">    <span class="k">def</span> <span class="nf">reverse</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 35</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="p">[::</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 36</span><span class="cl">
</span></span><span class="line"><span class="ln"> 37</span><span class="cl">    <span class="k">def</span> <span class="nf">split</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">delimiter</span><span class="p">:</span> <span class="nb">str</span> <span class="o">=</span> <span class="s2">&#34; &#34;</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 38</span><span class="cl">        <span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="n">delimiter</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 39</span><span class="cl">
</span></span><span class="line"><span class="ln"> 40</span><span class="cl">    <span class="k">def</span> <span class="nf">char_frequency</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 41</span><span class="cl">        <span class="n">freq</span> <span class="o">=</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 42</span><span class="cl">        <span class="k">for</span> <span class="n">c</span> <span class="ow">in</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 43</span><span class="cl">            <span class="n">freq</span><span class="p">[</span><span class="n">c</span><span class="p">]</span> <span class="o">=</span> <span class="n">freq</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="mi">0</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln"> 44</span><span class="cl">        <span class="k">return</span> <span class="n">freq</span>
</span></span><span class="line"><span class="ln"> 45</span><span class="cl">
</span></span><span class="line"><span class="ln"> 46</span><span class="cl">    <span class="k">def</span> <span class="nf">word_count</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 47</span><span class="cl">        <span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">split</span><span class="p">())</span>
</span></span><span class="line"><span class="ln"> 48</span><span class="cl">
</span></span><span class="line"><span class="ln"> 49</span><span class="cl">    <span class="k">def</span> <span class="nf">count_occurrences</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">substring</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">int</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 50</span><span class="cl">        <span class="n">count</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 51</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 52</span><span class="cl">        <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 53</span><span class="cl">            <span class="n">pos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">,</span> <span class="n">start</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 54</span><span class="cl">            <span class="k">if</span> <span class="n">pos</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 55</span><span class="cl">                <span class="k">break</span>
</span></span><span class="line"><span class="ln"> 56</span><span class="cl">            <span class="n">count</span> <span class="o">+=</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln"> 57</span><span class="cl">            <span class="n">start</span> <span class="o">=</span> <span class="n">pos</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">substring</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 58</span><span class="cl">        <span class="k">return</span> <span class="n">count</span>
</span></span><span class="line"><span class="ln"> 59</span><span class="cl">
</span></span><span class="line"><span class="ln"> 60</span><span class="cl">    <span class="k">def</span> <span class="nf">find_all</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">substring</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">list</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 61</span><span class="cl">        <span class="n">positions</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 62</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span>
</span></span><span class="line"><span class="ln"> 63</span><span class="cl">        <span class="k">while</span> <span class="kc">True</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 64</span><span class="cl">            <span class="n">pos</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">_content</span><span class="o">.</span><span class="n">find</span><span class="p">(</span><span class="n">substring</span><span class="p">,</span> <span class="n">start</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 65</span><span class="cl">            <span class="k">if</span> <span class="n">pos</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 66</span><span class="cl">                <span class="k">break</span>
</span></span><span class="line"><span class="ln"> 67</span><span class="cl">            <span class="n">positions</span><span class="o">.</span><span class="n">append</span><span class="p">(</span><span class="n">pos</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 68</span><span class="cl">            <span class="n">start</span> <span class="o">=</span> <span class="n">pos</span> <span class="o">+</span> <span class="nb">len</span><span class="p">(</span><span class="n">substring</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 69</span><span class="cl">        <span class="k">return</span> <span class="n">positions</span>
</span></span><span class="line"><span class="ln"> 70</span><span class="cl">
</span></span><span class="line"><span class="ln"> 71</span><span class="cl"><span class="k">def</span> <span class="nf">benchmark</span><span class="p">(</span><span class="n">func</span><span class="p">:</span> <span class="n">Callable</span><span class="p">[[],</span> <span class="n">Any</span><span class="p">],</span>
</span></span><span class="line"><span class="ln"> 72</span><span class="cl">              <span class="n">iterations</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">1000</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 73</span><span class="cl">              <span class="n">warmup</span><span class="p">:</span> <span class="nb">int</span> <span class="o">=</span> <span class="mi">100</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">dict</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 74</span><span class="cl">    <span class="s2">&#34;&#34;&#34;執行效能測試並回傳統計資料&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 75</span><span class="cl">    <span class="c1"># 預熱</span>
</span></span><span class="line"><span class="ln"> 76</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">warmup</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 77</span><span class="cl">        <span class="n">func</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 78</span><span class="cl">
</span></span><span class="line"><span class="ln"> 79</span><span class="cl">    <span class="c1"># 正式測試</span>
</span></span><span class="line"><span class="ln"> 80</span><span class="cl">    <span class="n">times</span> <span class="o">=</span> <span class="p">[]</span>
</span></span><span class="line"><span class="ln"> 81</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">iterations</span><span class="p">):</span>
</span></span><span class="line"><span class="ln"> 82</span><span class="cl">        <span class="n">start</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 83</span><span class="cl">        <span class="n">func</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 84</span><span class="cl">        <span class="n">end</span> <span class="o">=</span> <span class="n">time</span><span class="o">.</span><span class="n">perf_counter</span><span class="p">()</span>
</span></span><span class="line"><span class="ln"> 85</span><span class="cl">        <span class="n">times</span><span class="o">.</span><span class="n">append</span><span class="p">((</span><span class="n">end</span> <span class="o">-</span> <span class="n">start</span><span class="p">)</span> <span class="o">*</span> <span class="mi">1000</span><span class="p">)</span>  <span class="c1"># 轉換為毫秒</span>
</span></span><span class="line"><span class="ln"> 86</span><span class="cl">
</span></span><span class="line"><span class="ln"> 87</span><span class="cl">    <span class="k">return</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 88</span><span class="cl">        <span class="s2">&#34;mean&#34;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">mean</span><span class="p">(</span><span class="n">times</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 89</span><span class="cl">        <span class="s2">&#34;stdev&#34;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">stdev</span><span class="p">(</span><span class="n">times</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 90</span><span class="cl">        <span class="s2">&#34;min&#34;</span><span class="p">:</span> <span class="nb">min</span><span class="p">(</span><span class="n">times</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 91</span><span class="cl">        <span class="s2">&#34;max&#34;</span><span class="p">:</span> <span class="nb">max</span><span class="p">(</span><span class="n">times</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 92</span><span class="cl">        <span class="s2">&#34;median&#34;</span><span class="p">:</span> <span class="n">statistics</span><span class="o">.</span><span class="n">median</span><span class="p">(</span><span class="n">times</span><span class="p">),</span>
</span></span><span class="line"><span class="ln"> 93</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 94</span><span class="cl">
</span></span><span class="line"><span class="ln"> 95</span><span class="cl"><span class="k">def</span> <span class="nf">generate_test_content</span><span class="p">(</span><span class="n">size</span><span class="p">:</span> <span class="nb">int</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln"> 96</span><span class="cl">    <span class="s2">&#34;&#34;&#34;產生測試用字串&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 97</span><span class="cl">    <span class="n">base</span> <span class="o">=</span> <span class="s2">&#34;Hello World! This is a test string for benchmarking. &#34;</span>
</span></span><span class="line"><span class="ln"> 98</span><span class="cl">    <span class="k">return</span> <span class="p">(</span><span class="n">base</span> <span class="o">*</span> <span class="p">(</span><span class="n">size</span> <span class="o">//</span> <span class="nb">len</span><span class="p">(</span><span class="n">base</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))[:</span><span class="n">size</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 99</span><span class="cl">
</span></span><span class="line"><span class="ln">100</span><span class="cl"><span class="k">def</span> <span class="nf">run_benchmarks</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">101</span><span class="cl">    <span class="s2">&#34;&#34;&#34;執行所有效能測試&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">102</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">70</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">103</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;StringProcessor 效能測試：pybind11 vs 純 Python&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">104</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">70</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">105</span><span class="cl">
</span></span><span class="line"><span class="ln">106</span><span class="cl">    <span class="n">sizes</span> <span class="o">=</span> <span class="p">[</span><span class="mi">1_000</span><span class="p">,</span> <span class="mi">10_000</span><span class="p">,</span> <span class="mi">100_000</span><span class="p">,</span> <span class="mi">1_000_000</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">107</span><span class="cl">
</span></span><span class="line"><span class="ln">108</span><span class="cl">    <span class="k">for</span> <span class="n">size</span> <span class="ow">in</span> <span class="n">sizes</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">109</span><span class="cl">        <span class="n">content</span> <span class="o">=</span> <span class="n">generate_test_content</span><span class="p">(</span><span class="n">size</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">110</span><span class="cl">        <span class="n">cpp_sp</span> <span class="o">=</span> <span class="n">StringProcessor</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">111</span><span class="cl">        <span class="n">py_sp</span> <span class="o">=</span> <span class="n">PyStringProcessor</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">112</span><span class="cl">
</span></span><span class="line"><span class="ln">113</span><span class="cl">        <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="se">\n</span><span class="s2">--- 字串長度：</span><span class="si">{</span><span class="n">size</span><span class="si">:</span><span class="s2">,</span><span class="si">}</span><span class="s2"> 字元 ---</span><span class="se">\n</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">114</span><span class="cl">
</span></span><span class="line"><span class="ln">115</span><span class="cl">        <span class="c1"># 測試項目</span>
</span></span><span class="line"><span class="ln">116</span><span class="cl">        <span class="n">tests</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">117</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;to_upper&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">to_upper</span><span class="p">(),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">to_upper</span><span class="p">()),</span>
</span></span><span class="line"><span class="ln">118</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;to_lower&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">to_lower</span><span class="p">(),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">to_lower</span><span class="p">()),</span>
</span></span><span class="line"><span class="ln">119</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;reverse&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">reverse</span><span class="p">(),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">reverse</span><span class="p">()),</span>
</span></span><span class="line"><span class="ln">120</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;char_frequency&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">char_frequency</span><span class="p">(),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">char_frequency</span><span class="p">()),</span>
</span></span><span class="line"><span class="ln">121</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;word_count&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">word_count</span><span class="p">(),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">word_count</span><span class="p">()),</span>
</span></span><span class="line"><span class="ln">122</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;count_occurrences&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">count_occurrences</span><span class="p">(</span><span class="s2">&#34;test&#34;</span><span class="p">),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">count_occurrences</span><span class="p">(</span><span class="s2">&#34;test&#34;</span><span class="p">)),</span>
</span></span><span class="line"><span class="ln">123</span><span class="cl">            <span class="p">(</span><span class="s2">&#34;find_all&#34;</span><span class="p">,</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">cpp_sp</span><span class="o">.</span><span class="n">find_all</span><span class="p">(</span><span class="s2">&#34;Hello&#34;</span><span class="p">),</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">py_sp</span><span class="o">.</span><span class="n">find_all</span><span class="p">(</span><span class="s2">&#34;Hello&#34;</span><span class="p">)),</span>
</span></span><span class="line"><span class="ln">124</span><span class="cl">        <span class="p">]</span>
</span></span><span class="line"><span class="ln">125</span><span class="cl">
</span></span><span class="line"><span class="ln">126</span><span class="cl">        <span class="k">for</span> <span class="n">name</span><span class="p">,</span> <span class="n">cpp_func</span><span class="p">,</span> <span class="n">py_func</span> <span class="ow">in</span> <span class="n">tests</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">127</span><span class="cl">            <span class="n">cpp_result</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">cpp_func</span><span class="p">,</span> <span class="n">iterations</span><span class="o">=</span><span class="mi">500</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">128</span><span class="cl">            <span class="n">py_result</span> <span class="o">=</span> <span class="n">benchmark</span><span class="p">(</span><span class="n">py_func</span><span class="p">,</span> <span class="n">iterations</span><span class="o">=</span><span class="mi">500</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">129</span><span class="cl">
</span></span><span class="line"><span class="ln">130</span><span class="cl">            <span class="n">speedup</span> <span class="o">=</span> <span class="n">py_result</span><span class="p">[</span><span class="s2">&#34;mean&#34;</span><span class="p">]</span> <span class="o">/</span> <span class="n">cpp_result</span><span class="p">[</span><span class="s2">&#34;mean&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">131</span><span class="cl">
</span></span><span class="line"><span class="ln">132</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;</span><span class="si">{</span><span class="n">name</span><span class="si">:</span><span class="s2">20s</span><span class="si">}</span><span class="s2">&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">133</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  C++:    </span><span class="si">{</span><span class="n">cpp_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">8.4f</span><span class="si">}</span><span class="s2"> ms (stdev: </span><span class="si">{</span><span class="n">cpp_result</span><span class="p">[</span><span class="s1">&#39;stdev&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.4f</span><span class="si">}</span><span class="s2">)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">134</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  Python: </span><span class="si">{</span><span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;mean&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">8.4f</span><span class="si">}</span><span class="s2"> ms (stdev: </span><span class="si">{</span><span class="n">py_result</span><span class="p">[</span><span class="s1">&#39;stdev&#39;</span><span class="p">]</span><span class="si">:</span><span class="s2">.4f</span><span class="si">}</span><span class="s2">)&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">135</span><span class="cl">            <span class="nb">print</span><span class="p">(</span><span class="sa">f</span><span class="s2">&#34;  加速比: </span><span class="si">{</span><span class="n">speedup</span><span class="si">:</span><span class="s2">.2f</span><span class="si">}</span><span class="s2">x&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">136</span><span class="cl">            <span class="nb">print</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">137</span><span class="cl">
</span></span><span class="line"><span class="ln">138</span><span class="cl">    <span class="nb">print</span><span class="p">(</span><span class="s2">&#34;=&#34;</span> <span class="o">*</span> <span class="mi">70</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">139</span><span class="cl">
</span></span><span class="line"><span class="ln">140</span><span class="cl"><span class="k">if</span> <span class="vm">__name__</span> <span class="o">==</span> <span class="s2">&#34;__main__&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">141</span><span class="cl">    <span class="n">run_benchmarks</span><span class="p">()</span></span></span></code></pre></div><h3 id="預期效能結果">預期效能結果</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">======================================================================
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">StringProcessor 效能測試：pybind11 vs 純 Python
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">======================================================================
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">--- 字串長度：1,000 字元 ---
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">to_upper
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">  C++:      0.0012 ms (stdev: 0.0003)
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">  Python:   0.0008 ms (stdev: 0.0002)
</span></span><span class="line"><span class="ln">10</span><span class="cl">  加速比: 0.67x
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">char_frequency
</span></span><span class="line"><span class="ln">13</span><span class="cl">  C++:      0.0089 ms (stdev: 0.0012)
</span></span><span class="line"><span class="ln">14</span><span class="cl">  Python:   0.0423 ms (stdev: 0.0045)
</span></span><span class="line"><span class="ln">15</span><span class="cl">  加速比: 4.75x
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">word_count
</span></span><span class="line"><span class="ln">18</span><span class="cl">  C++:      0.0034 ms (stdev: 0.0008)
</span></span><span class="line"><span class="ln">19</span><span class="cl">  Python:   0.0028 ms (stdev: 0.0006)
</span></span><span class="line"><span class="ln">20</span><span class="cl">  加速比: 0.82x
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl">--- 字串長度：100,000 字元 ---
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">to_upper
</span></span><span class="line"><span class="ln">25</span><span class="cl">  C++:      0.0892 ms (stdev: 0.0089)
</span></span><span class="line"><span class="ln">26</span><span class="cl">  Python:   0.0634 ms (stdev: 0.0067)
</span></span><span class="line"><span class="ln">27</span><span class="cl">  加速比: 0.71x
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">char_frequency
</span></span><span class="line"><span class="ln">30</span><span class="cl">  C++:      0.7823 ms (stdev: 0.0456)
</span></span><span class="line"><span class="ln">31</span><span class="cl">  Python:   4.2341 ms (stdev: 0.2134)
</span></span><span class="line"><span class="ln">32</span><span class="cl">  加速比: 5.41x
</span></span><span class="line"><span class="ln">33</span><span class="cl">
</span></span><span class="line"><span class="ln">34</span><span class="cl">count_occurrences
</span></span><span class="line"><span class="ln">35</span><span class="cl">  C++:      0.0234 ms (stdev: 0.0034)
</span></span><span class="line"><span class="ln">36</span><span class="cl">  Python:   0.0567 ms (stdev: 0.0078)
</span></span><span class="line"><span class="ln">37</span><span class="cl">  加速比: 2.42x
</span></span><span class="line"><span class="ln">38</span><span class="cl">
</span></span><span class="line"><span class="ln">39</span><span class="cl">find_all
</span></span><span class="line"><span class="ln">40</span><span class="cl">  C++:      0.0312 ms (stdev: 0.0045)
</span></span><span class="line"><span class="ln">41</span><span class="cl">  Python:   0.0823 ms (stdev: 0.0098)
</span></span><span class="line"><span class="ln">42</span><span class="cl">  加速比: 2.64x
</span></span><span class="line"><span class="ln">43</span><span class="cl">
</span></span><span class="line"><span class="ln">44</span><span class="cl">======================================================================</span></span></code></pre></div><h3 id="效能分析">效能分析</h3>
<table>
  <thead>
      <tr>
          <th>操作類型</th>
          <th>C++ 優勢</th>
          <th>說明</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>字元頻率統計</strong></td>
          <td>4-6x</td>
          <td>C++ unordered_map 比 Python dict 更快</td>
      </tr>
      <tr>
          <td><strong>搜尋操作</strong></td>
          <td>2-3x</td>
          <td>C++ string::find 效率高</td>
      </tr>
      <tr>
          <td><strong>大小寫轉換</strong></td>
          <td>0.7x</td>
          <td>Python 內建函式已高度優化</td>
      </tr>
      <tr>
          <td><strong>單字計數</strong></td>
          <td>0.8-1x</td>
          <td>Python split() 非常高效</td>
      </tr>
  </tbody>
</table>
<p><strong>重點觀察</strong>：</p>
<ol>
<li><strong>不是所有操作都能加速</strong>：Python 的內建字串方法（如 <code>upper()</code>、<code>split()</code>）已經用 C 實作，pybind11 包裝反而增加呼叫開銷</li>
<li><strong>複雜操作效益明顯</strong>：需要多次迴圈或資料結構操作的方法（如字元頻率統計）獲益最大</li>
<li><strong>資料量影響顯著</strong>：資料量越大，C++ 的優勢越明顯</li>
</ol>
<h2 id="設計權衡">設計權衡</h2>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>純 Python</th>
          <th>pybind11 C++ 綁定</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>開發速度</strong></td>
          <td>快</td>
          <td>中（需要 C++ 開發經驗）</td>
      </tr>
      <tr>
          <td><strong>效能</strong></td>
          <td>基準</td>
          <td>特定操作 2-6x 加速</td>
      </tr>
      <tr>
          <td><strong>記憶體使用</strong></td>
          <td>較高</td>
          <td>較低（C++ 記憶體管理）</td>
      </tr>
      <tr>
          <td><strong>除錯難度</strong></td>
          <td>低</td>
          <td>中高（需要 C++ 除錯工具）</td>
      </tr>
      <tr>
          <td><strong>部署複雜度</strong></td>
          <td>簡單</td>
          <td>需要編譯環境</td>
      </tr>
      <tr>
          <td><strong>可維護性</strong></td>
          <td>高</td>
          <td>中（需要維護兩種語言）</td>
      </tr>
  </tbody>
</table>
<h3 id="何時使用-pybind11-綁定-c-類別">何時使用 pybind11 綁定 C++ 類別？</h3>
<p><strong>適合使用</strong>：</p>
<ul>
<li>已有成熟的 C++ 程式庫需要在 Python 中使用</li>
<li>需要精細的記憶體管理</li>
<li>效能瓶頸在資料結構操作而非 I/O</li>
<li>需要與其他 C++ 系統整合</li>
</ul>
<p><strong>不建議使用</strong>：</p>
<ul>
<li>純字串處理（Python 內建已很快）</li>
<li>簡單的資料容器（用 Python dataclass 更簡潔）</li>
<li>快速原型開發</li>
<li>團隊沒有 C++ 經驗</li>
</ul>
<h2 id="練習">練習</h2>
<h3 id="基礎練習">基礎練習</h3>
<p>擴展 StringProcessor，新增以下方法：</p>
<ol>
<li><code>join(separator: str, strings: list[str])</code> - 用分隔符串接字串列表</li>
<li><code>pad_left(width: int, char: str)</code> - 左側填充字元</li>
<li><code>pad_right(width: int, char: str)</code> - 右側填充字元</li>
</ol>
<h3 id="進階練習">進階練習</h3>
<p>建立一個 <code>DataBuffer</code> 類別，展示：</p>
<ol>
<li>使用 <code>std::vector&lt;uint8_t&gt;</code> 儲存二進位資料</li>
<li>支援 Python buffer protocol（可與 NumPy 互通）</li>
<li>實作切片操作（<code>__getitem__</code> 支援 slice）</li>
</ol>
<h3 id="挑戰題">挑戰題</h3>
<p>比較三種綁定方式的效能：</p>
<ol>
<li>pybind11 直接綁定</li>
<li>pybind11 + 釋放 GIL</li>
<li>使用 NumPy 陣列避免資料複製</li>
</ol>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://pybind11.readthedocs.io/en/stable/classes.html">pybind11 官方文件：類別</a></li>
<li><a href="https://pybind11.readthedocs.io/en/stable/operators.html">pybind11 官方文件：運算子重載</a></li>
<li><a href="https://pybind11.readthedocs.io/en/stable/advanced/smart_ptrs.html">pybind11 官方文件：智慧指標</a></li>
<li><a href="https://pybind11.readthedocs.io/en/stable/advanced/functions.html#return-value-policies">pybind11 記憶體管理最佳實踐</a></li>
</ul>
<hr>
<p><em>返回：<a href="/blog/python-advanced/05-c-extensions/case-studies/" data-link-title="案例研究" data-link-desc="基於 .claude/lib 實際程式碼的 C 擴展案例">案例研究</a></em>
<em>返回：<a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組五：用 C 擴展 Python</a></em></p>
]]></content:encoded></item><item><title>4.3 pybind11：現代 C++ 綁定</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/pybind11/</link><pubDate>Tue, 20 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/pybind11/</guid><description>&lt;p>本章介紹 pybind11，一個輕量級的 header-only C++ 函式庫，用於建立 Python 綁定。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>理解 pybind11 的設計哲學&lt;/li>
&lt;li>建立函式和類別綁定&lt;/li>
&lt;li>處理 NumPy 陣列&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="原理層pybind11-的設計哲學">【原理層】pybind11 的設計哲學&lt;/h2>
&lt;h3 id="為什麼需要-pybind11">為什麼需要 pybind11？&lt;/h3>
&lt;p>傳統的 Python C API 非常繁瑣：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-c" data-lang="c">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">// 傳統 Python C API
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">static&lt;/span> &lt;span class="n">PyObject&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="nf">add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">PyObject&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">self&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">PyObject&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">args&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl"> &lt;span class="kt">int&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">!&lt;/span>&lt;span class="nf">PyArg_ParseTuple&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">args&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;ii&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">b&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nf">PyLong_FromLong&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="k">static&lt;/span> &lt;span class="n">PyMethodDef&lt;/span> &lt;span class="n">methods&lt;/span>&lt;span class="p">[]&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="s">&amp;#34;add&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">add&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">METH_VARARGS&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;Add two integers&amp;#34;&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl"> &lt;span class="p">{&lt;/span>&lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">&lt;span class="k">static&lt;/span> &lt;span class="k">struct&lt;/span> &lt;span class="n">PyModuleDef&lt;/span> &lt;span class="n">module&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl"> &lt;span class="n">PyModuleDef_HEAD_INIT&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl"> &lt;span class="s">&amp;#34;example&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl"> &lt;span class="nb">NULL&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl"> &lt;span class="o">-&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl"> &lt;span class="n">methods&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="n">PyMODINIT_FUNC&lt;/span> &lt;span class="nf">PyInit_example&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">void&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="nf">PyModule_Create&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">module&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>pybind11 讓這變得簡單：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1">// pybind11
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;pybind11/pybind11.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="n">PYBIND11_MODULE&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">example&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="n">m&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">def&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;add&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">add&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;Add two integers&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="header-only-設計">Header-only 設計&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">pybind11 的特點：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">├── Header-only：不需要編譯函式庫
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">├── C++11：使用現代 C++ 特性
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">├── 自動型別轉換：Python ↔ C++ 型別
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">├── 最小化模板程式碼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">└── 與 NumPy 無縫整合&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="型別轉換原理">型別轉換原理&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">Python 呼叫 C++ 函式時：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">Python int ──→ pybind11 type_caster ──→ C++ int
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">Python str ──→ pybind11 type_caster ──→ std::string
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">Python list ──→ pybind11 type_caster ──→ std::vector&amp;lt;T&amp;gt;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">回傳時反向轉換&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="設計層開發環境設定">【設計層】開發環境設定&lt;/h2>
&lt;h3 id="安裝-pybind11">安裝 pybind11&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-bash" data-lang="bash">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 1：pip 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">pip install pybind11
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 2：conda 安裝&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">conda install -c conda-forge pybind11
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1"># 方法 3：系統套件管理器&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">&lt;span class="c1"># Ubuntu/Debian&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">sudo apt install pybind11-dev
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1"># macOS&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">brew install pybind11&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="專案結構">專案結構&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">my_project/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">├── CMakeLists.txt # CMake 建構檔
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">├── pyproject.toml # Python 打包設定
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">├── src/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">│ └── example.cpp # C++ 原始碼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">└── tests/
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> └── test_example.py # 測試&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="最小-cmakeliststxt">最小 CMakeLists.txt&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmake" data-lang="cmake">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">&lt;span class="nb">cmake_minimum_required&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">VERSION&lt;/span> &lt;span class="s">3.15&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="nb">project&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">example&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># 找到 pybind11
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">find_package&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">pybind11&lt;/span> &lt;span class="s">REQUIRED&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">&lt;span class="err">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">&lt;span class="err">&lt;/span>&lt;span class="c"># 建立 Python 模組
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">8&lt;/span>&lt;span class="cl">&lt;span class="c">&lt;/span>&lt;span class="nb">pybind11_add_module&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">example&lt;/span> &lt;span class="s">src/example.cpp&lt;/span>&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="使用-setuppy簡單專案">使用 setup.py（簡單專案）&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-python" data-lang="python">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="c1"># setup.py&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">setuptools&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">setup&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="kn">from&lt;/span> &lt;span class="nn">pybind11.setup_helpers&lt;/span> &lt;span class="kn">import&lt;/span> &lt;span class="n">Pybind11Extension&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">build_ext&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">&lt;span class="n">ext_modules&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">[&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl"> &lt;span class="n">Pybind11Extension&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl"> &lt;span class="s2">&amp;#34;example&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="p">[&lt;/span>&lt;span class="s2">&amp;#34;src/example.cpp&amp;#34;&lt;/span>&lt;span class="p">],&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl"> &lt;span class="p">),&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">&lt;span class="p">]&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="n">setup&lt;/span>&lt;span class="p">(&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="n">name&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="s2">&amp;#34;example&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl"> &lt;span class="n">ext_modules&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="n">ext_modules&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl"> &lt;span class="n">cmdclass&lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="s2">&amp;#34;build_ext&amp;#34;&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="n">build_ext&lt;/span>&lt;span class="p">},&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="p">)&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;h2 id="實作層基礎綁定">【實作層】基礎綁定&lt;/h2>
&lt;h3 id="函式綁定">函式綁定&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;pybind11/pybind11.h&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;string&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">&lt;span class="k">namespace&lt;/span> &lt;span class="n">py&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">pybind11&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">&lt;span class="c1">// 簡單函式
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="nf">add&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">&lt;span class="c1">// 帶預設參數
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">double&lt;/span> &lt;span class="nf">divide&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">double&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">double&lt;/span> &lt;span class="n">b&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">1.0&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">/&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">&lt;span class="c1">// 多載函式
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="nf">multiply&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">int&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">&lt;span class="kt">double&lt;/span> &lt;span class="nf">multiply&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="kt">double&lt;/span> &lt;span class="n">a&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">double&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="n">a&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="n">b&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">&lt;span class="c1">// 接受字串
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span> &lt;span class="n">greet&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">const&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">name&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="s">&amp;#34;Hello, &amp;#34;&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="n">name&lt;/span> &lt;span class="o">+&lt;/span> &lt;span class="s">&amp;#34;!&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">&lt;span class="n">PYBIND11_MODULE&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">example&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl"> &lt;span class="n">m&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">doc&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="s">&amp;#34;Example module&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 基本綁定
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">29&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">def&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;add&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">add&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;Add two integers&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">30&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">31&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 帶預設參數
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">32&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">def&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;divide&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">divide&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;Divide two numbers&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">33&lt;/span>&lt;span class="cl"> &lt;span class="n">py&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">arg&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;a&amp;#34;&lt;/span>&lt;span class="p">),&lt;/span> &lt;span class="n">py&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">arg&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;b&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="mf">1.0&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">34&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">35&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 處理多載：需要明確指定簽名
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">36&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">def&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;multiply&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">py&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">overload_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">multiply&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">37&lt;/span>&lt;span class="cl"> &lt;span class="n">m&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">def&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;multiply&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">py&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">overload_cast&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">double&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="kt">double&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">multiply&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">38&lt;/span>&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">39&lt;/span>&lt;span class="cl"> &lt;span class="c1">// 字串函式
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">40&lt;/span>&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">m&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">def&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;greet&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">greet&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;Greet someone&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">41&lt;/span>&lt;span class="cl">&lt;span class="p">}&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Python 使用：&lt;/p></description><content:encoded><![CDATA[<p>本章介紹 pybind11，一個輕量級的 header-only C++ 函式庫，用於建立 Python 綁定。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>理解 pybind11 的設計哲學</li>
<li>建立函式和類別綁定</li>
<li>處理 NumPy 陣列</li>
</ol>
<hr>
<h2 id="原理層pybind11-的設計哲學">【原理層】pybind11 的設計哲學</h2>
<h3 id="為什麼需要-pybind11">為什麼需要 pybind11？</h3>
<p>傳統的 Python C API 非常繁瑣：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-c" data-lang="c"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// 傳統 Python C API
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="k">static</span> <span class="n">PyObject</span><span class="o">*</span> <span class="nf">add</span><span class="p">(</span><span class="n">PyObject</span><span class="o">*</span> <span class="n">self</span><span class="p">,</span> <span class="n">PyObject</span><span class="o">*</span> <span class="n">args</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">    <span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="o">!</span><span class="nf">PyArg_ParseTuple</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="s">&#34;ii&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">a</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">b</span><span class="p">))</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">        <span class="k">return</span> <span class="nb">NULL</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">return</span> <span class="nf">PyLong_FromLong</span><span class="p">(</span><span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="k">static</span> <span class="n">PyMethodDef</span> <span class="n">methods</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="p">{</span><span class="s">&#34;add&#34;</span><span class="p">,</span> <span class="n">add</span><span class="p">,</span> <span class="n">METH_VARARGS</span><span class="p">,</span> <span class="s">&#34;Add two integers&#34;</span><span class="p">},</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="p">{</span><span class="nb">NULL</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="nb">NULL</span><span class="p">}</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="k">static</span> <span class="k">struct</span> <span class="n">PyModuleDef</span> <span class="n">module</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="n">PyModuleDef_HEAD_INIT</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="s">&#34;example&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="nb">NULL</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="o">-</span><span class="mi">1</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">methods</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="n">PyMODINIT_FUNC</span> <span class="nf">PyInit_example</span><span class="p">(</span><span class="kt">void</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="k">return</span> <span class="nf">PyModule_Create</span><span class="p">(</span><span class="o">&amp;</span><span class="n">module</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>pybind11 讓這變得簡單：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1">// pybind11
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&lt;pybind11/pybind11.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="kt">int</span> <span class="nf">add</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    <span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="n">PYBIND11_MODULE</span><span class="p">(</span><span class="n">example</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;add&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">add</span><span class="p">,</span> <span class="s">&#34;Add two integers&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h3 id="header-only-設計">Header-only 設計</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">pybind11 的特點：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── Header-only：不需要編譯函式庫
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── C++11：使用現代 C++ 特性
</span></span><span class="line"><span class="ln">4</span><span class="cl">├── 自動型別轉換：Python ↔ C++ 型別
</span></span><span class="line"><span class="ln">5</span><span class="cl">├── 最小化模板程式碼
</span></span><span class="line"><span class="ln">6</span><span class="cl">└── 與 NumPy 無縫整合</span></span></code></pre></div><h3 id="型別轉換原理">型別轉換原理</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">Python 呼叫 C++ 函式時：
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl">Python int  ──→  pybind11 type_caster  ──→  C++ int
</span></span><span class="line"><span class="ln">4</span><span class="cl">Python str  ──→  pybind11 type_caster  ──→  std::string
</span></span><span class="line"><span class="ln">5</span><span class="cl">Python list ──→  pybind11 type_caster  ──→  std::vector&lt;T&gt;
</span></span><span class="line"><span class="ln">6</span><span class="cl">
</span></span><span class="line"><span class="ln">7</span><span class="cl">回傳時反向轉換</span></span></code></pre></div><hr>
<h2 id="設計層開發環境設定">【設計層】開發環境設定</h2>
<h3 id="安裝-pybind11">安裝 pybind11</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># 方法 1：pip 安裝</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">pip install pybind11
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 方法 2：conda 安裝</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">conda install -c conda-forge pybind11
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"># 方法 3：系統套件管理器</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"># Ubuntu/Debian</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">sudo apt install pybind11-dev
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1"># macOS</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">brew install pybind11</span></span></code></pre></div><h3 id="專案結構">專案結構</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">my_project/
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── CMakeLists.txt        # CMake 建構檔
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── pyproject.toml        # Python 打包設定
</span></span><span class="line"><span class="ln">4</span><span class="cl">├── src/
</span></span><span class="line"><span class="ln">5</span><span class="cl">│   └── example.cpp       # C++ 原始碼
</span></span><span class="line"><span class="ln">6</span><span class="cl">└── tests/
</span></span><span class="line"><span class="ln">7</span><span class="cl">    └── test_example.py   # 測試</span></span></code></pre></div><h3 id="最小-cmakeliststxt">最小 CMakeLists.txt</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="ln">1</span><span class="cl"><span class="nb">cmake_minimum_required</span><span class="p">(</span><span class="s">VERSION</span> <span class="s">3.15</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="err"></span><span class="nb">project</span><span class="p">(</span><span class="s">example</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="err"></span><span class="c"># 找到 pybind11
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="c"></span><span class="nb">find_package</span><span class="p">(</span><span class="s">pybind11</span> <span class="s">REQUIRED</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="err"></span><span class="c"># 建立 Python 模組
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="c"></span><span class="nb">pybind11_add_module</span><span class="p">(</span><span class="s">example</span> <span class="s">src/example.cpp</span><span class="p">)</span></span></span></code></pre></div><h3 id="使用-setuppy簡單專案">使用 setup.py（簡單專案）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># setup.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">from</span> <span class="nn">setuptools</span> <span class="kn">import</span> <span class="n">setup</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">from</span> <span class="nn">pybind11.setup_helpers</span> <span class="kn">import</span> <span class="n">Pybind11Extension</span><span class="p">,</span> <span class="n">build_ext</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="n">ext_modules</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="n">Pybind11Extension</span><span class="p">(</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">        <span class="s2">&#34;example&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="p">[</span><span class="s2">&#34;src/example.cpp&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="p">),</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="n">setup</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="n">name</span><span class="o">=</span><span class="s2">&#34;example&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="n">ext_modules</span><span class="o">=</span><span class="n">ext_modules</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">cmdclass</span><span class="o">=</span><span class="p">{</span><span class="s2">&#34;build_ext&#34;</span><span class="p">:</span> <span class="n">build_ext</span><span class="p">},</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="p">)</span></span></span></code></pre></div><hr>
<h2 id="實作層基礎綁定">【實作層】基礎綁定</h2>
<h3 id="函式綁定">函式綁定</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;pybind11/pybind11.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">namespace</span> <span class="n">py</span> <span class="o">=</span> <span class="n">pybind11</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="c1">// 簡單函式
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">add</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="k">return</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c1">// 帶預設參數
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"></span><span class="kt">double</span> <span class="nf">divide</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="k">return</span> <span class="n">a</span> <span class="o">/</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c1">// 多載函式
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"></span><span class="kt">int</span> <span class="nf">multiply</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">,</span> <span class="kt">int</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">a</span> <span class="o">*</span> <span class="n">b</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="kt">double</span> <span class="nf">multiply</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span> <span class="k">return</span> <span class="n">a</span> <span class="o">*</span> <span class="n">b</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c1">// 接受字串
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c1"></span><span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">greet</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">name</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="k">return</span> <span class="s">&#34;Hello, &#34;</span> <span class="o">+</span> <span class="n">name</span> <span class="o">+</span> <span class="s">&#34;!&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="n">PYBIND11_MODULE</span><span class="p">(</span><span class="n">example</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">doc</span><span class="p">()</span> <span class="o">=</span> <span class="s">&#34;Example module&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="c1">// 基本綁定
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="c1"></span>    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;add&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">add</span><span class="p">,</span> <span class="s">&#34;Add two integers&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="c1">// 帶預設參數
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="c1"></span>    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;divide&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">divide</span><span class="p">,</span> <span class="s">&#34;Divide two numbers&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">          <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;a&#34;</span><span class="p">),</span> <span class="n">py</span><span class="o">::</span><span class="n">arg</span><span class="p">(</span><span class="s">&#34;b&#34;</span><span class="p">)</span> <span class="o">=</span> <span class="mf">1.0</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="c1">// 處理多載：需要明確指定簽名
</span></span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="c1"></span>    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;multiply&#34;</span><span class="p">,</span> <span class="n">py</span><span class="o">::</span><span class="n">overload_cast</span><span class="o">&lt;</span><span class="kt">int</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">multiply</span><span class="p">));</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;multiply&#34;</span><span class="p">,</span> <span class="n">py</span><span class="o">::</span><span class="n">overload_cast</span><span class="o">&lt;</span><span class="kt">double</span><span class="p">,</span> <span class="kt">double</span><span class="o">&gt;</span><span class="p">(</span><span class="o">&amp;</span><span class="n">multiply</span><span class="p">));</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">
</span></span><span class="line"><span class="ln">39</span><span class="cl">    <span class="c1">// 字串函式
</span></span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="c1"></span>    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;greet&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">greet</span><span class="p">,</span> <span class="s">&#34;Greet someone&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><p>Python 使用：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="kn">import</span> <span class="nn">example</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">example</span><span class="o">.</span><span class="n">add</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span>           <span class="c1"># 3</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">example</span><span class="o">.</span><span class="n">divide</span><span class="p">(</span><span class="mi">10</span><span class="p">,</span> <span class="mi">2</span><span class="p">))</span>       <span class="c1"># 5.0</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">example</span><span class="o">.</span><span class="n">divide</span><span class="p">(</span><span class="mi">10</span><span class="p">))</span>          <span class="c1"># 10.0（使用預設值）</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">example</span><span class="o">.</span><span class="n">multiply</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">))</span>      <span class="c1"># 12</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">example</span><span class="o">.</span><span class="n">multiply</span><span class="p">(</span><span class="mf">1.5</span><span class="p">,</span> <span class="mf">2.0</span><span class="p">))</span>  <span class="c1"># 3.0</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="nb">print</span><span class="p">(</span><span class="n">example</span><span class="o">.</span><span class="n">greet</span><span class="p">(</span><span class="s2">&#34;pybind11&#34;</span><span class="p">))</span>   <span class="c1"># Hello, pybind11!</span></span></span></code></pre></div><h3 id="類別綁定">類別綁定</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;pybind11/pybind11.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">namespace</span> <span class="n">py</span> <span class="o">=</span> <span class="n">pybind11</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">class</span> <span class="nc">Pet</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">Pet</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">name</span><span class="p">,</span> <span class="kt">int</span> <span class="n">age</span><span class="p">)</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">        <span class="o">:</span> <span class="n">name_</span><span class="p">(</span><span class="n">name</span><span class="p">),</span> <span class="n">age_</span><span class="p">(</span><span class="n">age</span><span class="p">)</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="c1">// getter/setter
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"></span>    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">get_name</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">name_</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="kt">void</span> <span class="nf">set_name</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">name</span><span class="p">)</span> <span class="p">{</span> <span class="n">name_</span> <span class="o">=</span> <span class="n">name</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="kt">int</span> <span class="nf">get_age</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">age_</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="kt">void</span> <span class="nf">set_age</span><span class="p">(</span><span class="kt">int</span> <span class="n">age</span><span class="p">)</span> <span class="p">{</span> <span class="n">age_</span> <span class="o">=</span> <span class="n">age</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="c1">// 方法
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1"></span>    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">describe</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">        <span class="k">return</span> <span class="n">name_</span> <span class="o">+</span> <span class="s">&#34; is &#34;</span> <span class="o">+</span> <span class="n">std</span><span class="o">::</span><span class="n">to_string</span><span class="p">(</span><span class="n">age_</span><span class="p">)</span> <span class="o">+</span> <span class="s">&#34; years old&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="k">private</span><span class="o">:</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="kt">int</span> <span class="n">age_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="n">PYBIND11_MODULE</span><span class="p">(</span><span class="n">example</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="n">py</span><span class="o">::</span><span class="n">class_</span><span class="o">&lt;</span><span class="n">Pet</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="s">&#34;Pet&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">        <span class="c1">// 建構子
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">init</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">
</span></span><span class="line"><span class="ln">33</span><span class="cl">        <span class="c1">// 屬性（getter/setter）
</span></span></span><span class="line"><span class="ln">34</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def_property</span><span class="p">(</span><span class="s">&#34;name&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">Pet</span><span class="o">::</span><span class="n">get_name</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">Pet</span><span class="o">::</span><span class="n">set_name</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">        <span class="p">.</span><span class="n">def_property</span><span class="p">(</span><span class="s">&#34;age&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">Pet</span><span class="o">::</span><span class="n">get_age</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">Pet</span><span class="o">::</span><span class="n">set_age</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="c1">// 唯讀屬性
</span></span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="c1"></span>        <span class="c1">// .def_property_readonly(&#34;name&#34;, &amp;Pet::get_name)
</span></span></span><span class="line"><span class="ln">39</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">40</span><span class="cl">        <span class="c1">// 方法
</span></span></span><span class="line"><span class="ln">41</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;describe&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">Pet</span><span class="o">::</span><span class="n">describe</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">
</span></span><span class="line"><span class="ln">43</span><span class="cl">        <span class="c1">// __repr__
</span></span></span><span class="line"><span class="ln">44</span><span class="cl"><span class="c1"></span>        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;__repr__&#34;</span><span class="p">,</span> <span class="p">[](</span><span class="k">const</span> <span class="n">Pet</span><span class="o">&amp;</span> <span class="n">p</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">            <span class="k">return</span> <span class="s">&#34;&lt;Pet &#39;&#34;</span> <span class="o">+</span> <span class="n">p</span><span class="p">.</span><span class="n">get_name</span><span class="p">()</span> <span class="o">+</span> <span class="s">&#34;&#39;&gt;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">        <span class="p">});</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h3 id="繼承">繼承</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;pybind11/pybind11.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;string&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">namespace</span> <span class="n">py</span> <span class="o">=</span> <span class="n">pybind11</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">class</span> <span class="nc">Animal</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="n">Animal</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">name</span><span class="p">)</span> <span class="o">:</span> <span class="n">name_</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="k">virtual</span> <span class="o">~</span><span class="n">Animal</span><span class="p">()</span> <span class="o">=</span> <span class="k">default</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">virtual</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">speak</span><span class="p">()</span> <span class="k">const</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>  <span class="c1">// 純虛函式
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="c1"></span>    <span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">name</span><span class="p">()</span> <span class="k">const</span> <span class="p">{</span> <span class="k">return</span> <span class="n">name_</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="k">protected</span><span class="o">:</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">name_</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="k">class</span> <span class="nc">Dog</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Animal</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">Dog</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">name</span><span class="p">)</span> <span class="o">:</span> <span class="n">Animal</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">speak</span><span class="p">()</span> <span class="k">const</span> <span class="k">override</span> <span class="p">{</span> <span class="k">return</span> <span class="s">&#34;Woof!&#34;</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="k">class</span> <span class="nc">Cat</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Animal</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">Cat</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">name</span><span class="p">)</span> <span class="o">:</span> <span class="n">Animal</span><span class="p">(</span><span class="n">name</span><span class="p">)</span> <span class="p">{}</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">speak</span><span class="p">()</span> <span class="k">const</span> <span class="k">override</span> <span class="p">{</span> <span class="k">return</span> <span class="s">&#34;Meow!&#34;</span><span class="p">;</span> <span class="p">}</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="c1">// 用於在 Python 中繼承 C++ 類別
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="c1"></span><span class="k">class</span> <span class="nc">PyAnimal</span> <span class="o">:</span> <span class="k">public</span> <span class="n">Animal</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="k">public</span><span class="o">:</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="k">using</span> <span class="n">Animal</span><span class="o">::</span><span class="n">Animal</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">string</span> <span class="n">speak</span><span class="p">()</span> <span class="k">const</span> <span class="k">override</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl">        <span class="n">PYBIND11_OVERRIDE_PURE</span><span class="p">(</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="n">Animal</span><span class="p">,</span> <span class="n">speak</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="p">};</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">
</span></span><span class="line"><span class="ln">40</span><span class="cl"><span class="n">PYBIND11_MODULE</span><span class="p">(</span><span class="n">example</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">    <span class="n">py</span><span class="o">::</span><span class="n">class_</span><span class="o">&lt;</span><span class="n">Animal</span><span class="p">,</span> <span class="n">PyAnimal</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="s">&#34;Animal&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">init</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;&gt;</span><span class="p">())</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;speak&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">Animal</span><span class="o">::</span><span class="n">speak</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">        <span class="p">.</span><span class="n">def_property_readonly</span><span class="p">(</span><span class="s">&#34;name&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">Animal</span><span class="o">::</span><span class="n">name</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">
</span></span><span class="line"><span class="ln">46</span><span class="cl">    <span class="n">py</span><span class="o">::</span><span class="n">class_</span><span class="o">&lt;</span><span class="n">Dog</span><span class="p">,</span> <span class="n">Animal</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="s">&#34;Dog&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">init</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;&gt;</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">
</span></span><span class="line"><span class="ln">49</span><span class="cl">    <span class="n">py</span><span class="o">::</span><span class="n">class_</span><span class="o">&lt;</span><span class="n">Cat</span><span class="p">,</span> <span class="n">Animal</span><span class="o">&gt;</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="s">&#34;Cat&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl">        <span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">init</span><span class="o">&lt;</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;&gt;</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><hr>
<h2 id="實作層進階功能">【實作層】進階功能</h2>
<h3 id="stl-容器轉換">STL 容器轉換</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;pybind11/pybind11.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;pybind11/stl.h&gt;</span><span class="cp">  </span><span class="c1">// 必須包含！
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&lt;vector&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;map&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;set&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="k">namespace</span> <span class="n">py</span> <span class="o">=</span> <span class="n">pybind11</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="c1">// 自動轉換 std::vector ↔ Python list
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"></span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">double_values</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;&amp;</span> <span class="n">input</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">int</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="n">result</span><span class="p">.</span><span class="n">reserve</span><span class="p">(</span><span class="n">input</span><span class="p">.</span><span class="n">size</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="nl">x</span> <span class="p">:</span> <span class="n">input</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="n">result</span><span class="p">.</span><span class="n">push_back</span><span class="p">(</span><span class="n">x</span> <span class="o">*</span> <span class="mi">2</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1">// std::map ↔ Python dict
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c1"></span><span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">count_chars</span><span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="o">&amp;</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">map</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">,</span> <span class="kt">int</span><span class="o">&gt;</span> <span class="n">counts</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">char</span> <span class="nl">c</span> <span class="p">:</span> <span class="n">s</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">        <span class="n">counts</span><span class="p">[</span><span class="n">std</span><span class="o">::</span><span class="n">string</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">c</span><span class="p">)]</span><span class="o">++</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">    <span class="k">return</span> <span class="n">counts</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">
</span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="n">PYBIND11_MODULE</span><span class="p">(</span><span class="n">example</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;double_values&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">double_values</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;count_chars&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">count_chars</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h3 id="numpy-整合">NumPy 整合</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;pybind11/pybind11.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;pybind11/numpy.h&gt;</span><span class="cp">  </span><span class="c1">// NumPy 支援
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"></span><span class="cp">#include</span> <span class="cpf">&lt;cmath&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">namespace</span> <span class="n">py</span> <span class="o">=</span> <span class="n">pybind11</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1">// 處理 NumPy 陣列
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"></span><span class="n">py</span><span class="o">::</span><span class="n">array_t</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">compute_sin</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">array_t</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">input</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="c1">// 取得輸入資訊
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"></span>    <span class="k">auto</span> <span class="n">buf</span> <span class="o">=</span> <span class="n">input</span><span class="p">.</span><span class="n">request</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">buf</span><span class="p">.</span><span class="n">ndim</span> <span class="o">!=</span> <span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="k">throw</span> <span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="p">(</span><span class="s">&#34;輸入必須是一維陣列&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="c1">// 建立輸出陣列
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="c1"></span>    <span class="n">py</span><span class="o">::</span><span class="n">array_t</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">(</span><span class="n">buf</span><span class="p">.</span><span class="n">size</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="k">auto</span> <span class="n">result_buf</span> <span class="o">=</span> <span class="n">result</span><span class="p">.</span><span class="n">request</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="c1">// 取得原始指標
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c1"></span>    <span class="kt">double</span><span class="o">*</span> <span class="n">in_ptr</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">buf</span><span class="p">.</span><span class="n">ptr</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="kt">double</span><span class="o">*</span> <span class="n">out_ptr</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">result_buf</span><span class="p">.</span><span class="n">ptr</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="c1">// 計算
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="c1"></span>    <span class="k">for</span> <span class="p">(</span><span class="n">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">buf</span><span class="p">.</span><span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="n">out_ptr</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">std</span><span class="o">::</span><span class="n">sin</span><span class="p">(</span><span class="n">in_ptr</span><span class="p">[</span><span class="n">i</span><span class="p">]);</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">
</span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="c1">// 多維陣列
</span></span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="c1"></span><span class="n">py</span><span class="o">::</span><span class="n">array_t</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">matrix_add</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">py</span><span class="o">::</span><span class="n">array_t</span><span class="o">&lt;</span><span class="kt">double</span><span class="p">,</span> <span class="n">py</span><span class="o">::</span><span class="n">array</span><span class="o">::</span><span class="n">c_style</span> <span class="o">|</span> <span class="n">py</span><span class="o">::</span><span class="n">array</span><span class="o">::</span><span class="n">forcecast</span><span class="o">&gt;</span> <span class="n">a</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">    <span class="n">py</span><span class="o">::</span><span class="n">array_t</span><span class="o">&lt;</span><span class="kt">double</span><span class="p">,</span> <span class="n">py</span><span class="o">::</span><span class="n">array</span><span class="o">::</span><span class="n">c_style</span> <span class="o">|</span> <span class="n">py</span><span class="o">::</span><span class="n">array</span><span class="o">::</span><span class="n">forcecast</span><span class="o">&gt;</span> <span class="n">b</span>
</span></span><span class="line"><span class="ln">36</span><span class="cl"><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">    <span class="k">auto</span> <span class="n">buf_a</span> <span class="o">=</span> <span class="n">a</span><span class="p">.</span><span class="n">request</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">38</span><span class="cl">    <span class="k">auto</span> <span class="n">buf_b</span> <span class="o">=</span> <span class="n">b</span><span class="p">.</span><span class="n">request</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">
</span></span><span class="line"><span class="ln">40</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">buf_a</span><span class="p">.</span><span class="n">ndim</span> <span class="o">!=</span> <span class="mi">2</span> <span class="o">||</span> <span class="n">buf_b</span><span class="p">.</span><span class="n">ndim</span> <span class="o">!=</span> <span class="mi">2</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">        <span class="k">throw</span> <span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="p">(</span><span class="s">&#34;需要二維陣列&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">
</span></span><span class="line"><span class="ln">44</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">buf_a</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">!=</span> <span class="n">buf_b</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">||</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">        <span class="n">buf_a</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">!=</span> <span class="n">buf_b</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">        <span class="k">throw</span> <span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="p">(</span><span class="s">&#34;陣列形狀必須相同&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">
</span></span><span class="line"><span class="ln">49</span><span class="cl">    <span class="n">size_t</span> <span class="n">rows</span> <span class="o">=</span> <span class="n">buf_a</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
</span></span><span class="line"><span class="ln">50</span><span class="cl">    <span class="n">size_t</span> <span class="n">cols</span> <span class="o">=</span> <span class="n">buf_a</span><span class="p">.</span><span class="n">shape</span><span class="p">[</span><span class="mi">1</span><span class="p">];</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">
</span></span><span class="line"><span class="ln">52</span><span class="cl">    <span class="n">py</span><span class="o">::</span><span class="n">array_t</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">result</span><span class="p">({</span><span class="n">rows</span><span class="p">,</span> <span class="n">cols</span><span class="p">});</span>
</span></span><span class="line"><span class="ln">53</span><span class="cl">    <span class="k">auto</span> <span class="n">buf_r</span> <span class="o">=</span> <span class="n">result</span><span class="p">.</span><span class="n">request</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">54</span><span class="cl">
</span></span><span class="line"><span class="ln">55</span><span class="cl">    <span class="kt">double</span><span class="o">*</span> <span class="n">ptr_a</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">buf_a</span><span class="p">.</span><span class="n">ptr</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl">    <span class="kt">double</span><span class="o">*</span> <span class="n">ptr_b</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">buf_b</span><span class="p">.</span><span class="n">ptr</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">57</span><span class="cl">    <span class="kt">double</span><span class="o">*</span> <span class="n">ptr_r</span> <span class="o">=</span> <span class="k">static_cast</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">*&gt;</span><span class="p">(</span><span class="n">buf_r</span><span class="p">.</span><span class="n">ptr</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">58</span><span class="cl">
</span></span><span class="line"><span class="ln">59</span><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="n">size_t</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">rows</span> <span class="o">*</span> <span class="n">cols</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">60</span><span class="cl">        <span class="n">ptr_r</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">ptr_a</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="n">ptr_b</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
</span></span><span class="line"><span class="ln">61</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">62</span><span class="cl">
</span></span><span class="line"><span class="ln">63</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">64</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">65</span><span class="cl">
</span></span><span class="line"><span class="ln">66</span><span class="cl"><span class="n">PYBIND11_MODULE</span><span class="p">(</span><span class="n">example</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">67</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;compute_sin&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">compute_sin</span><span class="p">,</span> <span class="s">&#34;Compute sin for each element&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">68</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;matrix_add&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">matrix_add</span><span class="p">,</span> <span class="s">&#34;Add two matrices&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">69</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h3 id="gil-管理">GIL 管理</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;pybind11/pybind11.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;thread&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;chrono&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">namespace</span> <span class="n">py</span> <span class="o">=</span> <span class="n">pybind11</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="c1">// 長時間 CPU 計算，應該釋放 GIL
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="c1"></span><span class="kt">double</span> <span class="nf">heavy_computation</span><span class="p">(</span><span class="kt">int</span> <span class="n">iterations</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="c1">// 釋放 GIL
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="c1"></span>    <span class="n">py</span><span class="o">::</span><span class="n">gil_scoped_release</span> <span class="n">release</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="kt">double</span> <span class="n">result</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">iterations</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="n">result</span> <span class="o">+=</span> <span class="n">std</span><span class="o">::</span><span class="n">sin</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="o">*</span> <span class="n">std</span><span class="o">::</span><span class="n">cos</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="c1">// GIL 自動重新獲取
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="c1"></span><span class="p">}</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c1">// 回呼 Python 函式，需要 GIL
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="c1"></span><span class="kt">void</span> <span class="nf">process_with_callback</span><span class="p">(</span><span class="n">py</span><span class="o">::</span><span class="n">function</span> <span class="n">callback</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">    <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="mi">10</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl">        <span class="c1">// 如果在無 GIL 的上下文中，需要獲取
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="c1"></span>        <span class="c1">// py::gil_scoped_acquire acquire;
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="n">callback</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">
</span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="c1">// 多執行緒範例
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="c1"></span><span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">parallel_compute</span><span class="p">(</span><span class="kt">int</span> <span class="n">n_threads</span><span class="p">,</span> <span class="kt">int</span> <span class="n">iterations</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="kt">double</span><span class="o">&gt;</span> <span class="n">results</span><span class="p">(</span><span class="n">n_threads</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">34</span><span class="cl">    <span class="n">std</span><span class="o">::</span><span class="n">vector</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="kr">thread</span><span class="o">&gt;</span> <span class="n">threads</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">35</span><span class="cl">
</span></span><span class="line"><span class="ln">36</span><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="ln">37</span><span class="cl">        <span class="c1">// 釋放 GIL 讓執行緒可以並行
</span></span></span><span class="line"><span class="ln">38</span><span class="cl"><span class="c1"></span>        <span class="n">py</span><span class="o">::</span><span class="n">gil_scoped_release</span> <span class="n">release</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">39</span><span class="cl">
</span></span><span class="line"><span class="ln">40</span><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">t</span> <span class="o">&lt;</span> <span class="n">n_threads</span><span class="p">;</span> <span class="n">t</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">41</span><span class="cl">            <span class="n">threads</span><span class="p">.</span><span class="n">emplace_back</span><span class="p">([</span><span class="o">&amp;</span><span class="n">results</span><span class="p">,</span> <span class="n">t</span><span class="p">,</span> <span class="n">iterations</span><span class="p">]()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">42</span><span class="cl">                <span class="kt">double</span> <span class="n">sum</span> <span class="o">=</span> <span class="mf">0.0</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">43</span><span class="cl">                <span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">&lt;</span> <span class="n">iterations</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">44</span><span class="cl">                    <span class="n">sum</span> <span class="o">+=</span> <span class="n">std</span><span class="o">::</span><span class="n">sin</span><span class="p">(</span><span class="n">t</span> <span class="o">+</span> <span class="n">i</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">45</span><span class="cl">                <span class="p">}</span>
</span></span><span class="line"><span class="ln">46</span><span class="cl">                <span class="n">results</span><span class="p">[</span><span class="n">t</span><span class="p">]</span> <span class="o">=</span> <span class="n">sum</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">47</span><span class="cl">            <span class="p">});</span>
</span></span><span class="line"><span class="ln">48</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln">49</span><span class="cl">
</span></span><span class="line"><span class="ln">50</span><span class="cl">        <span class="k">for</span> <span class="p">(</span><span class="k">auto</span><span class="o">&amp;</span> <span class="kr">thread</span> <span class="o">:</span> <span class="n">threads</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">51</span><span class="cl">            <span class="kr">thread</span><span class="p">.</span><span class="n">join</span><span class="p">();</span>
</span></span><span class="line"><span class="ln">52</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln">53</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">54</span><span class="cl">
</span></span><span class="line"><span class="ln">55</span><span class="cl">    <span class="k">return</span> <span class="n">results</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">56</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">57</span><span class="cl">
</span></span><span class="line"><span class="ln">58</span><span class="cl"><span class="n">PYBIND11_MODULE</span><span class="p">(</span><span class="n">example</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">59</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;heavy_computation&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">heavy_computation</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">60</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;process_with_callback&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">process_with_callback</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">61</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;parallel_compute&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">parallel_compute</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">62</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><h3 id="異常處理">異常處理</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cpp" data-lang="cpp"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;pybind11/pybind11.h&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="cp">#include</span> <span class="cpf">&lt;stdexcept&gt;</span><span class="cp">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="cp"></span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="k">namespace</span> <span class="n">py</span> <span class="o">=</span> <span class="n">pybind11</span><span class="p">;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="kt">double</span> <span class="nf">safe_divide</span><span class="p">(</span><span class="kt">double</span> <span class="n">a</span><span class="p">,</span> <span class="kt">double</span> <span class="n">b</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="k">if</span> <span class="p">(</span><span class="n">b</span> <span class="o">==</span> <span class="mf">0.0</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">        <span class="k">throw</span> <span class="n">std</span><span class="o">::</span><span class="n">invalid_argument</span><span class="p">(</span><span class="s">&#34;除數不能為零&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="k">return</span> <span class="n">a</span> <span class="o">/</span> <span class="n">b</span><span class="p">;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="kt">void</span> <span class="nf">custom_exception_example</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">    <span class="c1">// 拋出特定的 Python 異常
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="c1"></span>    <span class="k">throw</span> <span class="n">py</span><span class="o">::</span><span class="n">value_error</span><span class="p">(</span><span class="s">&#34;這是一個 ValueError&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="n">PYBIND11_MODULE</span><span class="p">(</span><span class="n">example</span><span class="p">,</span> <span class="n">m</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="c1">// std::invalid_argument 自動轉換為 ValueError
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c1"></span>    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;safe_divide&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">safe_divide</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">
</span></span><span class="line"><span class="ln">22</span><span class="cl">    <span class="n">m</span><span class="p">.</span><span class="n">def</span><span class="p">(</span><span class="s">&#34;custom_exception&#34;</span><span class="p">,</span> <span class="o">&amp;</span><span class="n">custom_exception_example</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="c1">// 註冊自訂異常
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="c1"></span>    <span class="k">static</span> <span class="n">py</span><span class="o">::</span><span class="n">exception</span><span class="o">&lt;</span><span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="o">&gt;</span> <span class="n">exc</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="s">&#34;CustomError&#34;</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">    <span class="n">py</span><span class="o">::</span><span class="n">register_exception_translator</span><span class="p">([](</span><span class="n">std</span><span class="o">::</span><span class="n">exception_ptr</span> <span class="n">p</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="k">try</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">            <span class="k">if</span> <span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="n">std</span><span class="o">::</span><span class="n">rethrow_exception</span><span class="p">(</span><span class="n">p</span><span class="p">);</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="p">}</span> <span class="k">catch</span> <span class="p">(</span><span class="k">const</span> <span class="n">std</span><span class="o">::</span><span class="n">runtime_error</span><span class="o">&amp;</span> <span class="n">e</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">            <span class="n">exc</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">what</span><span class="p">());</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="ln">32</span><span class="cl">    <span class="p">});</span>
</span></span><span class="line"><span class="ln">33</span><span class="cl"><span class="p">}</span></span></span></code></pre></div><hr>
<h2 id="建構現代化建構方式">【建構】現代化建構方式</h2>
<h3 id="scikit-build-core推薦">scikit-build-core（推薦）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># pyproject.toml</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="p">[</span><span class="nx">build-system</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="nx">requires</span> <span class="p">=</span> <span class="p">[</span><span class="s2">&#34;scikit-build-core&gt;=0.5&#34;</span><span class="p">,</span> <span class="s2">&#34;pybind11&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="nx">build-backend</span> <span class="p">=</span> <span class="s2">&#34;scikit_build_core.build&#34;</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="p">[</span><span class="nx">project</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="nx">name</span> <span class="p">=</span> <span class="s2">&#34;my-cpp-extension&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="nx">version</span> <span class="p">=</span> <span class="s2">&#34;0.1.0&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="nx">requires-python</span> <span class="p">=</span> <span class="s2">&#34;&gt;=3.8&#34;</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="p">[</span><span class="nx">tool</span><span class="p">.</span><span class="nx">scikit-build</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="nx">wheel</span><span class="p">.</span><span class="nx">packages</span> <span class="p">=</span> <span class="p">[</span><span class="s2">&#34;src/my_package&#34;</span><span class="p">]</span></span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-cmake" data-lang="cmake"><span class="line"><span class="ln">1</span><span class="cl"><span class="c"># CMakeLists.txt
</span></span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="c"></span><span class="nb">cmake_minimum_required</span><span class="p">(</span><span class="s">VERSION</span> <span class="s">3.15</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="err"></span><span class="nb">project</span><span class="p">(</span><span class="s">my_cpp_extension</span> <span class="s">LANGUAGES</span> <span class="s">CXX</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="err"></span><span class="nb">find_package</span><span class="p">(</span><span class="s">pybind11</span> <span class="s">CONFIG</span> <span class="s">REQUIRED</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="err"></span><span class="nb">pybind11_add_module</span><span class="p">(</span><span class="s">_core</span> <span class="s">src/core.cpp</span><span class="p">)</span><span class="err">
</span></span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="err">
</span></span></span><span class="line"><span class="ln">9</span><span class="cl"><span class="err"></span><span class="nb">install</span><span class="p">(</span><span class="s">TARGETS</span> <span class="s">_core</span> <span class="s">DESTINATION</span> <span class="s">.</span><span class="p">)</span></span></span></code></pre></div><h3 id="meson-python">meson-python</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="ln">1</span><span class="cl"><span class="c"># pyproject.toml</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="p">[</span><span class="nx">build-system</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl"><span class="nx">requires</span> <span class="p">=</span> <span class="p">[</span><span class="s2">&#34;meson-python&#34;</span><span class="p">,</span> <span class="s2">&#34;pybind11&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="nx">build-backend</span> <span class="p">=</span> <span class="s2">&#34;mesonpy&#34;</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl"><span class="p">[</span><span class="nx">project</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl"><span class="nx">name</span> <span class="p">=</span> <span class="s2">&#34;my-cpp-extension&#34;</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl"><span class="nx">version</span> <span class="p">=</span> <span class="s2">&#34;0.1.0&#34;</span></span></span></code></pre></div>




<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-meson" data-lang="meson"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># meson.build</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w"></span><span class="nb">project</span><span class="p">(</span><span class="s">&#39;my-cpp-extension&#39;</span><span class="p">,</span><span class="w"> </span><span class="s">&#39;cpp&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">  </span><span class="n">version</span><span class="p">:</span><span class="w"> </span><span class="s">&#39;0.1.0&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w">  </span><span class="n">default_options</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="s">&#39;cpp_std=c++17&#39;</span><span class="p">]</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w"></span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w"></span><span class="n">pybind11</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">dependency</span><span class="p">(</span><span class="s">&#39;pybind11&#39;</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w"></span><span class="n">py</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nn">import</span><span class="p">(</span><span class="s">&#39;python&#39;</span><span class="p">).</span><span class="n">find_installation</span><span class="p">(</span><span class="n">pure</span><span class="p">:</span><span class="w"> </span><span class="kc">false</span><span class="p">)</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w"></span><span class="n">py</span><span class="p">.</span><span class="n">extension_module</span><span class="p">(</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">  </span><span class="s">&#39;_core&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">  </span><span class="s">&#39;src/core.cpp&#39;</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">  </span><span class="n">dependencies</span><span class="p">:</span><span class="w"> </span><span class="n">pybind11</span><span class="p">,</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">  </span><span class="n">install</span><span class="p">:</span><span class="w"> </span><span class="kc">true</span><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w"></span><span class="p">)</span></span></span></code></pre></div><hr>
<h2 id="比較pybind11-vs-nanobind">【比較】pybind11 vs nanobind</h2>
<h3 id="nanobind-簡介">nanobind 簡介</h3>
<p>nanobind 是 pybind11 作者開發的下一代工具：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">nanobind vs pybind11：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">nanobind:
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── 更小的二進位檔案（~3-5x 減少）
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">├── 更快的編譯時間
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">├── 需要 C++17
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">├── 更嚴格的型別檢查
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">└── 更好的 Free-threading 支援
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">pybind11:
</span></span><span class="line"><span class="ln">11</span><span class="cl">├── 更成熟、更多文件
</span></span><span class="line"><span class="ln">12</span><span class="cl">├── C++11 即可
</span></span><span class="line"><span class="ln">13</span><span class="cl">├── 更廣泛的社群支援
</span></span><span class="line"><span class="ln">14</span><span class="cl">└── 更多現有專案使用</span></span></code></pre></div><h3 id="選擇建議">選擇建議</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">選擇 pybind11：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">- 需要支援舊編譯器（C++11）
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">- 需要豐富的文件和範例
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">- 現有專案已使用 pybind11
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">選擇 nanobind：
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">- 新專案
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">- 追求最小二進位大小
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">- 需要更好的 Free-threading 支援
</span></span><span class="line"><span class="ln">10</span><span class="cl">- 可以使用 C++17</span></span></code></pre></div><hr>
<h2 id="思考題">思考題</h2>
<ol>
<li>pybind11 如何實現 Python 和 C++ 之間的自動型別轉換？</li>
<li>什麼時候應該在 C++ 程式碼中釋放 GIL？有什麼風險？</li>
<li>為什麼 pybind11 使用 header-only 設計？這有什麼優缺點？</li>
</ol>
<h2 id="實作練習">實作練習</h2>
<ol>
<li>使用 pybind11 包裝一個簡單的 C++ 類別（如二維向量），支援運算子重載</li>
<li>實現一個接受 NumPy 陣列的 C++ 函式，計算陣列的移動平均</li>
<li>比較 pybind11 和 Cython 在相同任務上的效能和程式碼複雜度</li>
</ol>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://pybind11.readthedocs.io/">pybind11 官方文件</a></li>
<li><a href="https://github.com/pybind/pybind11">pybind11 GitHub</a></li>
<li><a href="https://github.com/wjakob/nanobind">nanobind</a></li>
<li><a href="https://scikit-build-core.readthedocs.io/">scikit-build-core</a></li>
</ul>
<hr>
<p><em>上一章：<a href="/blog/python-advanced/05-c-extensions/cython/" data-link-title="4.2 Cython：Python 語法的 C 速度" data-link-desc="使用 Cython 加速 Python 程式碼">Cython</a></em>
<em>下一章：<a href="/blog/python-advanced/05-c-extensions/when-to-use/" data-link-title="4.4 選擇指南與效能比較" data-link-desc="比較不同 C 擴展工具的適用場景">選擇指南</a></em></p>
]]></content:encoded></item><item><title>4.4 選擇指南與效能比較</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/when-to-use/</link><pubDate>Tue, 20 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/when-to-use/</guid><description>&lt;p>本章比較各種 C 擴展工具，幫助你在不同場景下做出正確選擇。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>根據專案需求選擇適合的工具&lt;/li>
&lt;li>理解各工具的效能差異&lt;/li>
&lt;li>評估維護成本與學習曲線&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="總覽c-擴展工具比較">【總覽】C 擴展工具比較&lt;/h2>
&lt;h3 id="工具定位">工具定位&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">┌─────────────────────────────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">│ C/C++ 擴展工具選擇 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">├─────────────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">│ 動態綁定（不需編譯） 靜態編譯 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">│ ├── ctypes ├── Cython │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">│ └── cffi (ABI) ├── cffi (API) │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">│ ├── pybind11 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">│ └── nanobind │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">├─────────────────────────────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">│ 適合 Python 背景 適合 C/C++ 背景 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">│ ├── ctypes ├── pybind11 │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">│ ├── cffi ├── nanobind │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">│ └── Cython └── Python C API │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">└─────────────────────────────────────────────────────────────────┘&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="快速比較表">快速比較表&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>特性&lt;/th>
 &lt;th>ctypes&lt;/th>
 &lt;th>cffi&lt;/th>
 &lt;th>Cython&lt;/th>
 &lt;th>pybind11&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>標準庫&lt;/td>
 &lt;td>是&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>否&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>不需編譯器&lt;/td>
 &lt;td>是&lt;/td>
 &lt;td>是 (ABI)&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>否&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>C++ 支援&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>否&lt;/td>
 &lt;td>有限&lt;/td>
 &lt;td>是&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>效能&lt;/td>
 &lt;td>2/5&lt;/td>
 &lt;td>3/5&lt;/td>
 &lt;td>4/5&lt;/td>
 &lt;td>4/5&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>學習曲線&lt;/td>
 &lt;td>低&lt;/td>
 &lt;td>低&lt;/td>
 &lt;td>中&lt;/td>
 &lt;td>中高&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>PyPy 支援&lt;/td>
 &lt;td>有限&lt;/td>
 &lt;td>是&lt;/td>
 &lt;td>有限&lt;/td>
 &lt;td>否&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="決策選擇流程圖">【決策】選擇流程圖&lt;/h2>
&lt;h3 id="主要決策點">主要決策點&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln"> 1&lt;/span>&lt;span class="cl">開始
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 2&lt;/span>&lt;span class="cl">│
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 3&lt;/span>&lt;span class="cl">├── Q1: 有 C/C++ 原始碼嗎？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 4&lt;/span>&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 5&lt;/span>&lt;span class="cl">│ ├── 沒有（只有 .so/.dll）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 6&lt;/span>&lt;span class="cl">│ │ └── → ctypes 或 cffi (ABI 模式)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 7&lt;/span>&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 8&lt;/span>&lt;span class="cl">│ └── 有原始碼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln"> 9&lt;/span>&lt;span class="cl">│ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">10&lt;/span>&lt;span class="cl">│ ├── Q2: 是 C++ 嗎？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">11&lt;/span>&lt;span class="cl">│ │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">12&lt;/span>&lt;span class="cl">│ │ ├── 是 C++
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">13&lt;/span>&lt;span class="cl">│ │ │ └── → pybind11 或 nanobind
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">14&lt;/span>&lt;span class="cl">│ │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">15&lt;/span>&lt;span class="cl">│ │ └── 是純 C
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">16&lt;/span>&lt;span class="cl">│ │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">17&lt;/span>&lt;span class="cl">│ │ ├── Q3: 想用 Python 語法寫？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">18&lt;/span>&lt;span class="cl">│ │ │ ├── 是 → Cython
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">19&lt;/span>&lt;span class="cl">│ │ │ └── 否 → cffi (API 模式)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">20&lt;/span>&lt;span class="cl">│ │ │
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">21&lt;/span>&lt;span class="cl">│ │ └── Q4: 需要優化現有 Python 程式碼？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">22&lt;/span>&lt;span class="cl">│ │ └── 是 → Cython
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">23&lt;/span>&lt;span class="cl">│
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">24&lt;/span>&lt;span class="cl">├── Q5: 需要在 PyPy 上執行？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">25&lt;/span>&lt;span class="cl">│ └── 是 → cffi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">26&lt;/span>&lt;span class="cl">│
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">27&lt;/span>&lt;span class="cl">└── Q6: 需要最小依賴？
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">28&lt;/span>&lt;span class="cl"> └── 是 → ctypes（標準庫）&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="場景決策表">場景決策表&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>場景&lt;/th>
 &lt;th>推薦工具&lt;/th>
 &lt;th>原因&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>呼叫系統 API (libc, Win32)&lt;/td>
 &lt;td>ctypes&lt;/td>
 &lt;td>標準庫，無需額外安裝&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>包裝現有 C 函式庫（無原始碼）&lt;/td>
 &lt;td>cffi (ABI)&lt;/td>
 &lt;td>較好的型別支援&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>包裝現有 C 函式庫（有原始碼）&lt;/td>
 &lt;td>cffi (API) 或 Cython&lt;/td>
 &lt;td>效能更好&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>包裝 C++ 函式庫&lt;/td>
 &lt;td>pybind11&lt;/td>
 &lt;td>C++ 原生支援&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>優化 Python 程式碼瓶頸&lt;/td>
 &lt;td>Cython&lt;/td>
 &lt;td>漸進式優化&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>新專案追求最小二進位&lt;/td>
 &lt;td>nanobind&lt;/td>
 &lt;td>現代設計&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>需要跨直譯器支援 (PyPy)&lt;/td>
 &lt;td>cffi&lt;/td>
 &lt;td>PyPy 官方推薦&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="效能基準測試比較">【效能】基準測試比較&lt;/h2>
&lt;h3 id="測試案例數值計算">測試案例：數值計算&lt;/h3>
&lt;p>計算 Fibonacci 數列第 n 項（迭代版）：&lt;/p></description><content:encoded><![CDATA[<p>本章比較各種 C 擴展工具，幫助你在不同場景下做出正確選擇。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>根據專案需求選擇適合的工具</li>
<li>理解各工具的效能差異</li>
<li>評估維護成本與學習曲線</li>
</ol>
<hr>
<h2 id="總覽c-擴展工具比較">【總覽】C 擴展工具比較</h2>
<h3 id="工具定位">工具定位</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">┌─────────────────────────────────────────────────────────────────┐
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">│                        C/C++ 擴展工具選擇                        │
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├─────────────────────────────────────────────────────────────────┤
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">│                                                                 │
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">│   動態綁定（不需編譯）          靜態編譯                         │
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">│   ├── ctypes                   ├── Cython                      │
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">│   └── cffi (ABI)               ├── cffi (API)                  │
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">│                                ├── pybind11                    │
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">│                                └── nanobind                    │
</span></span><span class="line"><span class="ln">10</span><span class="cl">│                                                                 │
</span></span><span class="line"><span class="ln">11</span><span class="cl">├─────────────────────────────────────────────────────────────────┤
</span></span><span class="line"><span class="ln">12</span><span class="cl">│   適合 Python 背景              適合 C/C++ 背景                  │
</span></span><span class="line"><span class="ln">13</span><span class="cl">│   ├── ctypes                   ├── pybind11                    │
</span></span><span class="line"><span class="ln">14</span><span class="cl">│   ├── cffi                     ├── nanobind                    │
</span></span><span class="line"><span class="ln">15</span><span class="cl">│   └── Cython                   └── Python C API                │
</span></span><span class="line"><span class="ln">16</span><span class="cl">│                                                                 │
</span></span><span class="line"><span class="ln">17</span><span class="cl">└─────────────────────────────────────────────────────────────────┘</span></span></code></pre></div><h3 id="快速比較表">快速比較表</h3>
<table>
  <thead>
      <tr>
          <th>特性</th>
          <th>ctypes</th>
          <th>cffi</th>
          <th>Cython</th>
          <th>pybind11</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>標準庫</td>
          <td>是</td>
          <td>否</td>
          <td>否</td>
          <td>否</td>
      </tr>
      <tr>
          <td>不需編譯器</td>
          <td>是</td>
          <td>是 (ABI)</td>
          <td>否</td>
          <td>否</td>
      </tr>
      <tr>
          <td>C++ 支援</td>
          <td>否</td>
          <td>否</td>
          <td>有限</td>
          <td>是</td>
      </tr>
      <tr>
          <td>效能</td>
          <td>2/5</td>
          <td>3/5</td>
          <td>4/5</td>
          <td>4/5</td>
      </tr>
      <tr>
          <td>學習曲線</td>
          <td>低</td>
          <td>低</td>
          <td>中</td>
          <td>中高</td>
      </tr>
      <tr>
          <td>PyPy 支援</td>
          <td>有限</td>
          <td>是</td>
          <td>有限</td>
          <td>否</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="決策選擇流程圖">【決策】選擇流程圖</h2>
<h3 id="主要決策點">主要決策點</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">開始
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">│
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├── Q1: 有 C/C++ 原始碼嗎？
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">│   │
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">│   ├── 沒有（只有 .so/.dll）
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">│   │   └── → ctypes 或 cffi (ABI 模式)
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">│   │
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">│   └── 有原始碼
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">│       │
</span></span><span class="line"><span class="ln">10</span><span class="cl">│       ├── Q2: 是 C++ 嗎？
</span></span><span class="line"><span class="ln">11</span><span class="cl">│       │   │
</span></span><span class="line"><span class="ln">12</span><span class="cl">│       │   ├── 是 C++
</span></span><span class="line"><span class="ln">13</span><span class="cl">│       │   │   └── → pybind11 或 nanobind
</span></span><span class="line"><span class="ln">14</span><span class="cl">│       │   │
</span></span><span class="line"><span class="ln">15</span><span class="cl">│       │   └── 是純 C
</span></span><span class="line"><span class="ln">16</span><span class="cl">│       │       │
</span></span><span class="line"><span class="ln">17</span><span class="cl">│       │       ├── Q3: 想用 Python 語法寫？
</span></span><span class="line"><span class="ln">18</span><span class="cl">│       │       │   ├── 是 → Cython
</span></span><span class="line"><span class="ln">19</span><span class="cl">│       │       │   └── 否 → cffi (API 模式)
</span></span><span class="line"><span class="ln">20</span><span class="cl">│       │       │
</span></span><span class="line"><span class="ln">21</span><span class="cl">│       │       └── Q4: 需要優化現有 Python 程式碼？
</span></span><span class="line"><span class="ln">22</span><span class="cl">│       │           └── 是 → Cython
</span></span><span class="line"><span class="ln">23</span><span class="cl">│
</span></span><span class="line"><span class="ln">24</span><span class="cl">├── Q5: 需要在 PyPy 上執行？
</span></span><span class="line"><span class="ln">25</span><span class="cl">│   └── 是 → cffi
</span></span><span class="line"><span class="ln">26</span><span class="cl">│
</span></span><span class="line"><span class="ln">27</span><span class="cl">└── Q6: 需要最小依賴？
</span></span><span class="line"><span class="ln">28</span><span class="cl">    └── 是 → ctypes（標準庫）</span></span></code></pre></div><h3 id="場景決策表">場景決策表</h3>
<table>
  <thead>
      <tr>
          <th>場景</th>
          <th>推薦工具</th>
          <th>原因</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>呼叫系統 API (libc, Win32)</td>
          <td>ctypes</td>
          <td>標準庫，無需額外安裝</td>
      </tr>
      <tr>
          <td>包裝現有 C 函式庫（無原始碼）</td>
          <td>cffi (ABI)</td>
          <td>較好的型別支援</td>
      </tr>
      <tr>
          <td>包裝現有 C 函式庫（有原始碼）</td>
          <td>cffi (API) 或 Cython</td>
          <td>效能更好</td>
      </tr>
      <tr>
          <td>包裝 C++ 函式庫</td>
          <td>pybind11</td>
          <td>C++ 原生支援</td>
      </tr>
      <tr>
          <td>優化 Python 程式碼瓶頸</td>
          <td>Cython</td>
          <td>漸進式優化</td>
      </tr>
      <tr>
          <td>新專案追求最小二進位</td>
          <td>nanobind</td>
          <td>現代設計</td>
      </tr>
      <tr>
          <td>需要跨直譯器支援 (PyPy)</td>
          <td>cffi</td>
          <td>PyPy 官方推薦</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="效能基準測試比較">【效能】基準測試比較</h2>
<h3 id="測試案例數值計算">測試案例：數值計算</h3>
<p>計算 Fibonacci 數列第 n 項（迭代版）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 純 Python 基準</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="k">def</span> <span class="nf">fib_python</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="k">if</span> <span class="n">n</span> <span class="o">&lt;=</span> <span class="mi">1</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl">        <span class="k">return</span> <span class="n">n</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">    <span class="k">for</span> <span class="n">_</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
</span></span><span class="line"><span class="ln">7</span><span class="cl">        <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
</span></span><span class="line"><span class="ln">8</span><span class="cl">    <span class="k">return</span> <span class="n">b</span></span></span></code></pre></div><h3 id="效能數據">效能數據</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">計算 fib(40)，執行 10000 次：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">工具              相對時間    說明
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">─────────────────────────────────────────
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">純 Python         1.00x      基準
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">ctypes            0.45x      呼叫 C 函式庫
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">cffi (ABI)        0.40x      動態載入
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">cffi (API)        0.15x      編譯後
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">Cython            0.08x      靜態型別
</span></span><span class="line"><span class="ln">10</span><span class="cl">pybind11          0.08x      C++ 編譯
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">注意：
</span></span><span class="line"><span class="ln">13</span><span class="cl">- 實際數據取決於具體任務
</span></span><span class="line"><span class="ln">14</span><span class="cl">- 數值計算 Cython 和 pybind11 接近
</span></span><span class="line"><span class="ln">15</span><span class="cl">- 字串處理 pybind11 通常更快（std::string）
</span></span><span class="line"><span class="ln">16</span><span class="cl">- 函式呼叫開銷：ctypes &gt; cffi ABI &gt; cffi API ≈ Cython ≈ pybind11</span></span></code></pre></div><h3 id="函式呼叫開銷測試">函式呼叫開銷測試</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="kn">import</span> <span class="nn">timeit</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="c1"># 測試空函式呼叫開銷</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="c1"># 每個工具都實現 def noop(): pass</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="n">results</span> <span class="o">=</span> <span class="s2">&#34;&#34;&#34;
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="s2">空函式呼叫 1,000,000 次：
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="s2">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="s2">工具              時間 (ms)   每次呼叫 (ns)
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="s2">───────────────────────────────────────────
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="s2">Python def        45          45
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="s2">ctypes           280         280
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="s2">cffi (ABI)       180         180
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="s2">cffi (API)        55          55
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="s2">Cython cdef       12          12  (只能從 Cython 呼叫)
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="s2">Cython cpdef      50          50
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="s2">pybind11          52          52
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="s2">&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">
</span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="c1"># 結論：</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c1"># - ctypes/cffi ABI 的呼叫開銷較大</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="c1"># - 對於頻繁呼叫的小函式，編譯方案更好</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="c1"># - Cython cdef 最快，但不能從 Python 直接呼叫</span></span></span></code></pre></div><h3 id="記憶體使用比較">記憶體使用比較</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">匯入空模組的記憶體增加：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">工具              額外記憶體
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">────────────────────────────
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">ctypes           ~50 KB
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">cffi             ~200 KB
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">Cython module    ~100 KB
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">pybind11 module  ~150 KB
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">編譯後的模組大小（簡單範例）：
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">工具              .so 檔案大小
</span></span><span class="line"><span class="ln">13</span><span class="cl">─────────────────────────────
</span></span><span class="line"><span class="ln">14</span><span class="cl">Cython           ~100 KB
</span></span><span class="line"><span class="ln">15</span><span class="cl">pybind11         ~200 KB
</span></span><span class="line"><span class="ln">16</span><span class="cl">nanobind         ~50 KB</span></span></code></pre></div><hr>
<h2 id="考量維護性與開發體驗">【考量】維護性與開發體驗</h2>
<h3 id="學習曲線">學習曲線</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">難度排序（由易到難）：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">1. ctypes
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">   - Python 標準庫
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">   - 不需要 C 知識（但需要理解 C 型別）
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">   - 文件完整
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">2. cffi
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">   - 需要寫 C 宣告
</span></span><span class="line"><span class="ln">10</span><span class="cl">   - ABI 模式很簡單
</span></span><span class="line"><span class="ln">11</span><span class="cl">   - API 模式需要建構設定
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">3. Cython
</span></span><span class="line"><span class="ln">14</span><span class="cl">   - Python 超集，逐步學習
</span></span><span class="line"><span class="ln">15</span><span class="cl">   - 需要理解 C 型別系統
</span></span><span class="line"><span class="ln">16</span><span class="cl">   - 建構系統有學習成本
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">4. pybind11
</span></span><span class="line"><span class="ln">19</span><span class="cl">   - 需要 C++ 知識
</span></span><span class="line"><span class="ln">20</span><span class="cl">   - 現代 C++ 語法
</span></span><span class="line"><span class="ln">21</span><span class="cl">   - 需要 CMake 或類似工具</span></span></code></pre></div><h3 id="除錯難度">除錯難度</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">除錯工具支援：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">ctypes:
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── 可以用 Python debugger
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">├── 段錯誤難以追蹤
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">└── 沒有型別檢查
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">cffi:
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">├── API 模式有較好的錯誤訊息
</span></span><span class="line"><span class="ln">10</span><span class="cl">├── 可以用 C debugger (gdb)
</span></span><span class="line"><span class="ln">11</span><span class="cl">└── ABI 模式錯誤較難理解
</span></span><span class="line"><span class="ln">12</span><span class="cl">
</span></span><span class="line"><span class="ln">13</span><span class="cl">Cython:
</span></span><span class="line"><span class="ln">14</span><span class="cl">├── 可以產生帶行號的 C 程式碼
</span></span><span class="line"><span class="ln">15</span><span class="cl">├── 支援 gdb/lldb
</span></span><span class="line"><span class="ln">16</span><span class="cl">├── cython -a 產生效能報告
</span></span><span class="line"><span class="ln">17</span><span class="cl">└── 支援 Python profiler
</span></span><span class="line"><span class="ln">18</span><span class="cl">
</span></span><span class="line"><span class="ln">19</span><span class="cl">pybind11:
</span></span><span class="line"><span class="ln">20</span><span class="cl">├── C++ 除錯器完整支援
</span></span><span class="line"><span class="ln">21</span><span class="cl">├── 異常會轉換為 Python 異常
</span></span><span class="line"><span class="ln">22</span><span class="cl">├── 編譯錯誤訊息可能很長
</span></span><span class="line"><span class="ln">23</span><span class="cl">└── 模板錯誤較難理解</span></span></code></pre></div><h3 id="ide-支援">IDE 支援</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">IDE / 編輯器支援程度：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">工具          型別提示    自動完成    語法高亮
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">─────────────────────────────────────────────
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">ctypes        2/5         2/5         4/5
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">cffi          2/5         2/5         4/5
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">Cython        3/5         3/5         3/5
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">pybind11      4/5         4/5         4/5
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">註：
</span></span><span class="line"><span class="ln">11</span><span class="cl">- Cython 有 VSCode 和 PyCharm 插件
</span></span><span class="line"><span class="ln">12</span><span class="cl">- pybind11 使用標準 C++，IDE 支援完整
</span></span><span class="line"><span class="ln">13</span><span class="cl">- ctypes/cffi 的 Python 部分支援完整</span></span></code></pre></div><hr>
<h2 id="案例知名專案的選擇">【案例】知名專案的選擇</h2>
<h3 id="numpy">NumPy</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">NumPy 的策略：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">核心計算:
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">└── Python C API + 自訂機制
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    - 歷史原因（比 pybind11 更早）
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    - 需要極致效能
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    - 大量使用 BLAS/LAPACK
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">周邊工具:
</span></span><span class="line"><span class="ln">10</span><span class="cl">└── Cython
</span></span><span class="line"><span class="ln">11</span><span class="cl">    - 部分輔助模組
</span></span><span class="line"><span class="ln">12</span><span class="cl">    - 與 NumPy 陣列整合良好</span></span></code></pre></div><h3 id="scipy">SciPy</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">SciPy 的策略：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">主要使用:
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── Cython（大部分新程式碼）
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">├── Fortran（歷史遺留的數值庫）
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">└── C（某些核心演算法）
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">選擇原因:
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">- Cython 與 NumPy 整合好
</span></span><span class="line"><span class="ln">10</span><span class="cl">- 漸進式優化現有 Python 程式碼
</span></span><span class="line"><span class="ln">11</span><span class="cl">- 科學計算社群熟悉</span></span></code></pre></div><h3 id="pytorch">PyTorch</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">PyTorch 的策略：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">C++ 核心:
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">└── pybind11
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    - 大量 C++ 程式碼
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    - 複雜的類別層級
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    - 自動微分需要 C++ 特性
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">選擇原因:
</span></span><span class="line"><span class="ln">10</span><span class="cl">- C++ 是主要開發語言
</span></span><span class="line"><span class="ln">11</span><span class="cl">- 需要 RAII、模板、繼承
</span></span><span class="line"><span class="ln">12</span><span class="cl">- 與 CUDA 程式碼整合</span></span></code></pre></div><h3 id="pillow-pil">Pillow (PIL)</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Pillow 的策略：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">影像處理核心:
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">└── Python C API
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    - 歷史遺留
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    - 底層記憶體操作
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">周邊功能:
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">└── 純 Python 或 ctypes
</span></span><span class="line"><span class="ln">10</span><span class="cl">    - 呼叫系統圖形庫</span></span></code></pre></div><h3 id="cryptography">cryptography</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">cryptography 的策略：
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl">主要使用:
</span></span><span class="line"><span class="ln">4</span><span class="cl">└── cffi
</span></span><span class="line"><span class="ln">5</span><span class="cl">    - 包裝 OpenSSL
</span></span><span class="line"><span class="ln">6</span><span class="cl">    - 需要 PyPy 支援
</span></span><span class="line"><span class="ln">7</span><span class="cl">    - 安全性考量（減少手動記憶體管理）</span></span></code></pre></div><hr>
<h2 id="建議實務選擇指南">【建議】實務選擇指南</h2>
<h3 id="新專案建議">新專案建議</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">2025 年新專案建議：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">場景 1: 優化 Python 程式碼
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">推薦: Cython
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">理由:
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">- 漸進式優化
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">- 熟悉的 Python 語法
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">- 與 NumPy 整合好
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">場景 2: 包裝現有 C++ 函式庫
</span></span><span class="line"><span class="ln">11</span><span class="cl">推薦: pybind11 或 nanobind
</span></span><span class="line"><span class="ln">12</span><span class="cl">理由:
</span></span><span class="line"><span class="ln">13</span><span class="cl">- C++ 原生支援
</span></span><span class="line"><span class="ln">14</span><span class="cl">- 現代化 API
</span></span><span class="line"><span class="ln">15</span><span class="cl">- 活躍的社群
</span></span><span class="line"><span class="ln">16</span><span class="cl">
</span></span><span class="line"><span class="ln">17</span><span class="cl">場景 3: 簡單呼叫系統 API
</span></span><span class="line"><span class="ln">18</span><span class="cl">推薦: ctypes
</span></span><span class="line"><span class="ln">19</span><span class="cl">理由:
</span></span><span class="line"><span class="ln">20</span><span class="cl">- 標準庫，無依賴
</span></span><span class="line"><span class="ln">21</span><span class="cl">- 簡單場景足夠
</span></span><span class="line"><span class="ln">22</span><span class="cl">
</span></span><span class="line"><span class="ln">23</span><span class="cl">場景 4: 需要 PyPy 支援
</span></span><span class="line"><span class="ln">24</span><span class="cl">推薦: cffi
</span></span><span class="line"><span class="ln">25</span><span class="cl">理由:
</span></span><span class="line"><span class="ln">26</span><span class="cl">- PyPy 官方推薦
</span></span><span class="line"><span class="ln">27</span><span class="cl">- 良好的效能</span></span></code></pre></div><h3 id="遷移建議">遷移建議</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">從 ctypes 遷移到更快的方案：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">如果瓶頸是呼叫頻率：
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">└── 考慮 cffi (API) 或 Cython
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">    - 減少每次呼叫的開銷
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">如果瓶頸是計算本身：
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">└── 考慮 Cython
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    - 可以優化 Python 迴圈
</span></span><span class="line"><span class="ln">10</span><span class="cl">    - 使用 C 型別
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">從 Cython 遷移到 pybind11：
</span></span><span class="line"><span class="ln">13</span><span class="cl">
</span></span><span class="line"><span class="ln">14</span><span class="cl">通常不需要：
</span></span><span class="line"><span class="ln">15</span><span class="cl">- Cython 和 pybind11 效能相近
</span></span><span class="line"><span class="ln">16</span><span class="cl">- 遷移成本高
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">考慮遷移如果：
</span></span><span class="line"><span class="ln">19</span><span class="cl">- 需要更多 C++ 特性
</span></span><span class="line"><span class="ln">20</span><span class="cl">- 團隊更熟悉 C++
</span></span><span class="line"><span class="ln">21</span><span class="cl">- 需要與 C++ 函式庫深度整合</span></span></code></pre></div><h3 id="混合使用">混合使用</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">可以在同一專案中混合使用：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">範例結構：
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">my_package/
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">├── _core.cpython-311-xxx.so    # Cython：核心計算
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">├── _bindings.cpython-311-xxx.so # pybind11：C++ 函式庫綁定
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">├── _ffi.py                      # cffi：簡單 C 呼叫
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">└── utils.py                     # 純 Python
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl">原則：
</span></span><span class="line"><span class="ln">11</span><span class="cl">- 選擇最適合該任務的工具
</span></span><span class="line"><span class="ln">12</span><span class="cl">- 保持介面一致（對使用者透明）
</span></span><span class="line"><span class="ln">13</span><span class="cl">- 文件記錄每個部分的技術選擇</span></span></code></pre></div><hr>
<h2 id="未來發展趨勢">【未來】發展趨勢</h2>
<h3 id="free-threading-影響">Free-threading 影響</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">Python 3.13+ Free-threading 的影響：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">需要注意的工具：
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── pybind11: 需要更新 GIL 管理方式
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">├── Cython: nogil 區塊的行為變化
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">└── cffi: 相對影響較小
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">趨勢：
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">- nanobind 已有 Free-threading 支援
</span></span><span class="line"><span class="ln">10</span><span class="cl">- pybind11 正在積極適應
</span></span><span class="line"><span class="ln">11</span><span class="cl">- Cython 3.1 計劃支援</span></span></code></pre></div><h3 id="hpy新一代-c-api">HPy：新一代 C API</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">HPy (https://hpyproject.org/)
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">目標：
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── 統一的 C API（跨直譯器）
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">├── 更好的 PyPy/GraalPy 支援
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">├── 為 Free-threading 設計
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">└── 簡化記憶體管理
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">狀態（2025）：
</span></span><span class="line"><span class="ln">10</span><span class="cl">- 仍在開發中
</span></span><span class="line"><span class="ln">11</span><span class="cl">- 部分專案開始採用
</span></span><span class="line"><span class="ln">12</span><span class="cl">- 長期可能取代 Python C API</span></span></code></pre></div><h3 id="建構系統演進">建構系統演進</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">建構系統趨勢：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">傳統：
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── setup.py + setuptools
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">└── 複雜且不標準
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">現代：
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">├── scikit-build-core + CMake
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">├── meson-python
</span></span><span class="line"><span class="ln">10</span><span class="cl">└── 統一使用 pyproject.toml
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">建議：
</span></span><span class="line"><span class="ln">13</span><span class="cl">- 新專案使用 scikit-build-core 或 meson-python
</span></span><span class="line"><span class="ln">14</span><span class="cl">- 舊專案可以繼續使用 setup.py
</span></span><span class="line"><span class="ln">15</span><span class="cl">- 避免複雜的建構邏輯</span></span></code></pre></div><hr>
<h2 id="總結">總結</h2>
<h3 id="選擇原則">選擇原則</h3>
<ol>
<li><strong>簡單優先</strong>：如果 ctypes 能滿足需求，就用 ctypes</li>
<li><strong>效能驅動</strong>：當效能成為瓶頸時，才考慮編譯方案</li>
<li><strong>團隊技能</strong>：選擇團隊熟悉的技術</li>
<li><strong>長期維護</strong>：考慮依賴的活躍度和未來發展</li>
</ol>
<h3 id="快速決策">快速決策</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">你應該使用：
</span></span><span class="line"><span class="ln">2</span><span class="cl">
</span></span><span class="line"><span class="ln">3</span><span class="cl">ctypes    → 簡單的系統 API 呼叫
</span></span><span class="line"><span class="ln">4</span><span class="cl">cffi      → 需要 PyPy 支援，或包裝 C 函式庫
</span></span><span class="line"><span class="ln">5</span><span class="cl">Cython    → 優化 Python 程式碼，或與 NumPy 密切整合
</span></span><span class="line"><span class="ln">6</span><span class="cl">pybind11  → 包裝 C++ 函式庫
</span></span><span class="line"><span class="ln">7</span><span class="cl">nanobind  → 新專案，追求最小化</span></span></code></pre></div><hr>
<h2 id="實作練習">實作練習</h2>
<ol>
<li>
<p>使用本章學到的四種工具，分別實現同一個函式（如快速排序），比較：</p>
<ul>
<li>程式碼行數</li>
<li>編譯時間</li>
<li>執行效能</li>
<li>除錯體驗</li>
</ul>
</li>
<li>
<p>選擇一個你熟悉的 C 函式庫，分別用 ctypes 和 cffi 包裝，比較開發體驗</p>
</li>
<li>
<p>將一個 Python 效能瓶頸用 Cython 優化，記錄優化過程和效能提升</p>
</li>
</ol>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://realpython.com/python-bindings-overview/">Real Python - Python Bindings Overview</a></li>
<li><a href="http://blog.behnel.de/posts/cython-pybind11-cffi-which-tool-to-choose.html">Stefan Behnel - Cython vs pybind11 vs cffi</a></li>
<li><a href="https://hpyproject.org/">HPy Project</a></li>
<li><a href="https://packaging.python.org/en/latest/guides/packaging-binary-extensions/">Python Packaging Guide - Binary Extensions</a></li>
</ul>
<hr>
<p><em>上一章：<a href="/blog/python-advanced/05-c-extensions/pybind11/" data-link-title="4.3 pybind11：現代 C&#43;&#43; 綁定" data-link-desc="使用 pybind11 建立 Python 與 C&#43;&#43; 的綁定">pybind11</a></em>
<em>下一模組：<a href="/blog/python-advanced/06-rust-extensions/" data-link-title="模組六：用 Rust 擴展 Python" data-link-desc="學習使用 PyO3 和 Maturin 用 Rust 擴展 Python">模組五：用 Rust 擴展 Python</a></em></p>
]]></content:encoded></item><item><title>6.5 封裝預編譯二進位</title><link>https://tarrragon.github.io/blog/python-advanced/07-packaging/bundled-binaries/</link><pubDate>Mon, 02 Feb 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/07-packaging/bundled-binaries/</guid><description>&lt;p>本章介紹 Python 套件封裝預編譯二進位的架構模式，讓 Python 能夠調用高效能的原生程式碼。&lt;/p>
&lt;h2 id="本章目標">本章目標&lt;/h2>
&lt;p>學完本章後，你將能夠：&lt;/p>
&lt;ol>
&lt;li>理解「Python 封裝二進位」的架構模式&lt;/li>
&lt;li>評估何時使用這種模式&lt;/li>
&lt;li>了解知名套件如何應用這種技術&lt;/li>
&lt;li>在純 Python 與封裝二進位之間做出正確選擇&lt;/li>
&lt;/ol>
&lt;hr>
&lt;h2 id="概念什麼是封裝預編譯二進位">【概念】什麼是封裝預編譯二進位？&lt;/h2>
&lt;h3 id="架構模式">架構模式&lt;/h3>
&lt;p>這種模式將其他語言（如 Go、Rust、C++）編譯的二進位檔案，包裝在 Python 套件中：&lt;/p>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">┌─────────────────────────────────────────┐
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">│ Python API（薄封裝層） │ ← 使用者接觸的介面
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">├─────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">│ subprocess / FFI / ctypes / cffi │ ← 呼叫機制
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">├─────────────────────────────────────────┤
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">│ 預編譯二進位（Go/Rust/C/C++） │ ← 實際執行邏輯
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl">└─────────────────────────────────────────┘&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="與-c-擴展的差異">與 C 擴展的差異&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>面向&lt;/th>
 &lt;th>C 擴展（模組四/五）&lt;/th>
 &lt;th>封裝預編譯二進位&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>編譯時機&lt;/td>
 &lt;td>安裝時編譯&lt;/td>
 &lt;td>發布前預編譯&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>使用者需求&lt;/td>
 &lt;td>可能需要編譯器&lt;/td>
 &lt;td>不需要編譯器&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>整合方式&lt;/td>
 &lt;td>Python C API / pybind11&lt;/td>
 &lt;td>subprocess / FFI&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>典型來源&lt;/td>
 &lt;td>專為 Python 寫的擴展&lt;/td>
 &lt;td>獨立的 CLI 工具或函式庫&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;hr>
&lt;h2 id="案例">【案例】&lt;/h2>
&lt;h3 id="tensorflow--pytorch">TensorFlow / PyTorch&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">TensorFlow 架構：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">├── Python API（tf.* 模組）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">│ └── 使用者撰寫的程式碼
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">├── 綁定層（pybind11）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">│ └── Python ↔ C++ 橋接
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl">└── C++ 核心 + CUDA
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">7&lt;/span>&lt;span class="cl"> └── 預編譯的運算核心&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>選擇原因&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>GPU 運算需要原生效能&lt;/li>
&lt;li>大量的 C++ 程式碼庫&lt;/li>
&lt;li>安裝時編譯太慢（數小時）&lt;/li>
&lt;/ul>
&lt;h3 id="cryptography">cryptography&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">cryptography 架構：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">├── Python API（cryptography.*)
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">├── cffi 綁定層
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">└── OpenSSL / BoringSSL
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> └── 預編譯的加密函式庫&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>選擇原因&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>加密演算法需要經過審計的實現&lt;/li>
&lt;li>效能關鍵&lt;/li>
&lt;li>支援 PyPy（cffi 是 PyPy 官方推薦）&lt;/li>
&lt;/ul>
&lt;h3 id="ruffpython-linter">ruff（Python Linter）&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">ruff 架構：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">├── Python 封裝（ruff 套件）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">│ └── 提供 CLI 和簡單 API
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">└── Rust 二進位
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl"> └── 實際的 lint 邏輯&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>選擇原因&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>追求極致速度（比 Flake8 快 10-100 倍）&lt;/li>
&lt;li>Rust 的記憶體安全&lt;/li>
&lt;li>作為獨立工具也可使用&lt;/li>
&lt;/ul>
&lt;h3 id="mermaid-asciipypi-封裝">mermaid-ascii（PyPI 封裝）&lt;/h3>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">osl-packages/mermaid-ascii 架構：
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">├── Python API（mermaid_ascii 模組）
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">│ └── mermaid_to_ascii() 函式
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">├── subprocess 呼叫
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">5&lt;/span>&lt;span class="cl">└── Go 編譯的 mermaid-ascii 二進位
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">6&lt;/span>&lt;span class="cl"> └── Mermaid → ASCII 轉換&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;strong>選擇原因&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>重用現有的 Go 實現&lt;/li>
&lt;li>不需要 Node.js 依賴&lt;/li>
&lt;li>提供 Python 友善的介面&lt;/li>
&lt;/ul>
&lt;hr>
&lt;h2 id="優點為什麼使用這種模式">【優點】為什麼使用這種模式？&lt;/h2>
&lt;h3 id="1-效能">1. 效能&lt;/h3>
&lt;p>核心邏輯用高效能語言實現，Python 只做介面：&lt;/p></description><content:encoded><![CDATA[<p>本章介紹 Python 套件封裝預編譯二進位的架構模式，讓 Python 能夠調用高效能的原生程式碼。</p>
<h2 id="本章目標">本章目標</h2>
<p>學完本章後，你將能夠：</p>
<ol>
<li>理解「Python 封裝二進位」的架構模式</li>
<li>評估何時使用這種模式</li>
<li>了解知名套件如何應用這種技術</li>
<li>在純 Python 與封裝二進位之間做出正確選擇</li>
</ol>
<hr>
<h2 id="概念什麼是封裝預編譯二進位">【概念】什麼是封裝預編譯二進位？</h2>
<h3 id="架構模式">架構模式</h3>
<p>這種模式將其他語言（如 Go、Rust、C++）編譯的二進位檔案，包裝在 Python 套件中：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">┌─────────────────────────────────────────┐
</span></span><span class="line"><span class="ln">2</span><span class="cl">│       Python API（薄封裝層）              │  ← 使用者接觸的介面
</span></span><span class="line"><span class="ln">3</span><span class="cl">├─────────────────────────────────────────┤
</span></span><span class="line"><span class="ln">4</span><span class="cl">│   subprocess / FFI / ctypes / cffi      │  ← 呼叫機制
</span></span><span class="line"><span class="ln">5</span><span class="cl">├─────────────────────────────────────────┤
</span></span><span class="line"><span class="ln">6</span><span class="cl">│   預編譯二進位（Go/Rust/C/C++）          │  ← 實際執行邏輯
</span></span><span class="line"><span class="ln">7</span><span class="cl">└─────────────────────────────────────────┘</span></span></code></pre></div><h3 id="與-c-擴展的差異">與 C 擴展的差異</h3>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>C 擴展（模組四/五）</th>
          <th>封裝預編譯二進位</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>編譯時機</td>
          <td>安裝時編譯</td>
          <td>發布前預編譯</td>
      </tr>
      <tr>
          <td>使用者需求</td>
          <td>可能需要編譯器</td>
          <td>不需要編譯器</td>
      </tr>
      <tr>
          <td>整合方式</td>
          <td>Python C API / pybind11</td>
          <td>subprocess / FFI</td>
      </tr>
      <tr>
          <td>典型來源</td>
          <td>專為 Python 寫的擴展</td>
          <td>獨立的 CLI 工具或函式庫</td>
      </tr>
  </tbody>
</table>
<hr>
<h2 id="案例">【案例】</h2>
<h3 id="tensorflow--pytorch">TensorFlow / PyTorch</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">TensorFlow 架構：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── Python API（tf.* 模組）
</span></span><span class="line"><span class="ln">3</span><span class="cl">│   └── 使用者撰寫的程式碼
</span></span><span class="line"><span class="ln">4</span><span class="cl">├── 綁定層（pybind11）
</span></span><span class="line"><span class="ln">5</span><span class="cl">│   └── Python ↔ C++ 橋接
</span></span><span class="line"><span class="ln">6</span><span class="cl">└── C++ 核心 + CUDA
</span></span><span class="line"><span class="ln">7</span><span class="cl">    └── 預編譯的運算核心</span></span></code></pre></div><p><strong>選擇原因</strong>：</p>
<ul>
<li>GPU 運算需要原生效能</li>
<li>大量的 C++ 程式碼庫</li>
<li>安裝時編譯太慢（數小時）</li>
</ul>
<h3 id="cryptography">cryptography</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">cryptography 架構：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── Python API（cryptography.*)
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── cffi 綁定層
</span></span><span class="line"><span class="ln">4</span><span class="cl">└── OpenSSL / BoringSSL
</span></span><span class="line"><span class="ln">5</span><span class="cl">    └── 預編譯的加密函式庫</span></span></code></pre></div><p><strong>選擇原因</strong>：</p>
<ul>
<li>加密演算法需要經過審計的實現</li>
<li>效能關鍵</li>
<li>支援 PyPy（cffi 是 PyPy 官方推薦）</li>
</ul>
<h3 id="ruffpython-linter">ruff（Python Linter）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">ruff 架構：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── Python 封裝（ruff 套件）
</span></span><span class="line"><span class="ln">3</span><span class="cl">│   └── 提供 CLI 和簡單 API
</span></span><span class="line"><span class="ln">4</span><span class="cl">└── Rust 二進位
</span></span><span class="line"><span class="ln">5</span><span class="cl">    └── 實際的 lint 邏輯</span></span></code></pre></div><p><strong>選擇原因</strong>：</p>
<ul>
<li>追求極致速度（比 Flake8 快 10-100 倍）</li>
<li>Rust 的記憶體安全</li>
<li>作為獨立工具也可使用</li>
</ul>
<h3 id="mermaid-asciipypi-封裝">mermaid-ascii（PyPI 封裝）</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">osl-packages/mermaid-ascii 架構：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── Python API（mermaid_ascii 模組）
</span></span><span class="line"><span class="ln">3</span><span class="cl">│   └── mermaid_to_ascii() 函式
</span></span><span class="line"><span class="ln">4</span><span class="cl">├── subprocess 呼叫
</span></span><span class="line"><span class="ln">5</span><span class="cl">└── Go 編譯的 mermaid-ascii 二進位
</span></span><span class="line"><span class="ln">6</span><span class="cl">    └── Mermaid → ASCII 轉換</span></span></code></pre></div><p><strong>選擇原因</strong>：</p>
<ul>
<li>重用現有的 Go 實現</li>
<li>不需要 Node.js 依賴</li>
<li>提供 Python 友善的介面</li>
</ul>
<hr>
<h2 id="優點為什麼使用這種模式">【優點】為什麼使用這種模式？</h2>
<h3 id="1-效能">1. 效能</h3>
<p>核心邏輯用高效能語言實現，Python 只做介面：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 使用者感受不到底層是 Rust</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="kn">import</span> <span class="nn">ruff</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="c1"># 實際上是呼叫 Rust 編譯的二進位</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl"><span class="n">result</span> <span class="o">=</span> <span class="n">ruff</span><span class="o">.</span><span class="n">check</span><span class="p">(</span><span class="s2">&#34;my_code.py&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="2-重用現有實現">2. 重用現有實現</h3>
<p>不需要用 Python 重寫已經穩定的程式碼：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">情境：有一個優秀的 Go CLI 工具
</span></span><span class="line"><span class="ln">2</span><span class="cl">選項 A：用 Python 重寫（大量工作）
</span></span><span class="line"><span class="ln">3</span><span class="cl">選項 B：封裝 Go 二進位（少量工作）← 通常更好</span></span></code></pre></div><h3 id="3-跨語言生態整合">3. 跨語言生態整合</h3>
<p>讓 Python 使用者能夠使用其他語言的優秀工具：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># Python 使用者不需要安裝 Go</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="kn">from</span> <span class="nn">mermaid_ascii</span> <span class="kn">import</span> <span class="n">mermaid_to_ascii</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="n">diagram</span> <span class="o">=</span> <span class="n">mermaid_to_ascii</span><span class="p">(</span><span class="s2">&#34;graph LR; A--&gt;B&#34;</span><span class="p">)</span></span></span></code></pre></div><h3 id="4-維護分離">4. 維護分離</h3>
<p>核心邏輯與 Python 封裝可以獨立更新：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">mermaid-ascii（Go）: v0.6.1 → v0.7.0（核心更新）
</span></span><span class="line"><span class="ln">2</span><span class="cl">mermaid-ascii（PyPI）: 0.6.1 → 0.7.0（同步更新封裝）</span></span></code></pre></div><hr>
<h2 id="缺點這種模式的限制">【缺點】這種模式的限制</h2>
<h3 id="1-平台依賴">1. 平台依賴</h3>
<p>需要為每個作業系統和 CPU 架構提供預編譯二進位：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">典型的 wheel 矩陣：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">├── manylinux_x86_64
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├── manylinux_aarch64
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── macosx_x86_64
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">├── macosx_arm64
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">└── win_amd64
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">缺點：
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">- 維護成本高
</span></span><span class="line"><span class="ln">10</span><span class="cl">- 新平台支援需要時間
</span></span><span class="line"><span class="ln">11</span><span class="cl">- CI/CD 複雜度增加</span></span></code></pre></div><h3 id="2-安裝體積">2. 安裝體積</h3>
<p>wheel 檔案較大（包含二進位）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">套件大小比較：
</span></span><span class="line"><span class="ln">2</span><span class="cl">純 Python 套件   ~50 KB
</span></span><span class="line"><span class="ln">3</span><span class="cl">封裝二進位套件   ~5-50 MB（依二進位大小）</span></span></code></pre></div><h3 id="3-除錯困難">3. 除錯困難</h3>
<p>錯誤可能發生在二進位層，難以追蹤：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln">1</span><span class="cl"><span class="c1"># 錯誤訊息可能是二進位的 stderr</span>
</span></span><span class="line"><span class="ln">2</span><span class="cl"><span class="k">try</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">3</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">some_binary_wrapper</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">4</span><span class="cl"><span class="k">except</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">CalledProcessError</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">5</span><span class="cl">    <span class="c1"># e.stderr 是二進位的錯誤訊息</span>
</span></span><span class="line"><span class="ln">6</span><span class="cl">    <span class="c1"># 可能不是 Python 友善的格式</span></span></span></code></pre></div><h3 id="4-無法修改核心邏輯">4. 無法修改核心邏輯</h3>
<p>想改變底層行為必須重編譯核心：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">如果你需要：
</span></span><span class="line"><span class="ln">2</span><span class="cl">- 修改演算法
</span></span><span class="line"><span class="ln">3</span><span class="cl">- 加入自訂功能
</span></span><span class="line"><span class="ln">4</span><span class="cl">- 修復底層 bug
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl">你必須：
</span></span><span class="line"><span class="ln">7</span><span class="cl">1. 修改原始語言的程式碼
</span></span><span class="line"><span class="ln">8</span><span class="cl">2. 重新編譯
</span></span><span class="line"><span class="ln">9</span><span class="cl">3. 重新打包 wheel</span></span></code></pre></div><h3 id="5-供應鏈風險">5. 供應鏈風險</h3>
<p>二進位來源需要信任：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">風險考量：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── 二進位是否來自可信來源？
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── 是否有可驗證的建構流程？
</span></span><span class="line"><span class="ln">4</span><span class="cl">└── 是否有安全審計？
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl">最佳實踐：
</span></span><span class="line"><span class="ln">7</span><span class="cl">├── 使用知名維護者的套件
</span></span><span class="line"><span class="ln">8</span><span class="cl">├── 檢查 GitHub Actions 等 CI 建構紀錄
</span></span><span class="line"><span class="ln">9</span><span class="cl">└── 考慮自行建構（如果可能）</span></span></code></pre></div><hr>
<h2 id="比較純-python-vs-封裝二進位">【比較】純 Python vs 封裝二進位</h2>
<h3 id="特性比較表">特性比較表</h3>
<table>
  <thead>
      <tr>
          <th>面向</th>
          <th>純 Python</th>
          <th>封裝預編譯二進位</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><strong>效能</strong></td>
          <td>較慢</td>
          <td>可達原生速度</td>
      </tr>
      <tr>
          <td><strong>可移植性</strong></td>
          <td>極佳（任何有 Python 的地方）</td>
          <td>受限於預編譯平台</td>
      </tr>
      <tr>
          <td><strong>除錯</strong></td>
          <td>容易（Python 工具鏈）</td>
          <td>困難（跨語言）</td>
      </tr>
      <tr>
          <td><strong>修改靈活度</strong></td>
          <td>高（直接修改程式碼）</td>
          <td>低（需重新編譯）</td>
      </tr>
      <tr>
          <td><strong>安裝體積</strong></td>
          <td>小</td>
          <td>大（含二進位）</td>
      </tr>
      <tr>
          <td><strong>依賴管理</strong></td>
          <td>簡單</td>
          <td>複雜</td>
      </tr>
      <tr>
          <td><strong>透明度</strong></td>
          <td>完全可見</td>
          <td>部分黑箱</td>
      </tr>
      <tr>
          <td><strong>開發速度</strong></td>
          <td>快（Python 生態）</td>
          <td>需要多語言技能</td>
      </tr>
  </tbody>
</table>
<h3 id="決策流程">決策流程</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">選擇純 Python 如果：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">├── 效能不是關鍵瓶頸
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├── 需要頻繁修改邏輯
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── 需要最大可移植性
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">├── 功能相對簡單
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">└── 希望保持程式碼透明
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">選擇封裝二進位如果：
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">├── 效能是關鍵需求
</span></span><span class="line"><span class="ln">10</span><span class="cl">├── 已有成熟的非 Python 實現
</span></span><span class="line"><span class="ln">11</span><span class="cl">├── 核心邏輯穩定，不常修改
</span></span><span class="line"><span class="ln">12</span><span class="cl">├── 需要系統級別的操作
</span></span><span class="line"><span class="ln">13</span><span class="cl">└── 安全性要求使用審計過的實現</span></span></code></pre></div><hr>
<h2 id="實作如何封裝二進位">【實作】如何封裝二進位</h2>
<h3 id="方法一subprocess-呼叫">方法一：subprocess 呼叫</h3>
<p>最簡單的封裝方式，適合 CLI 工具：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># my_wrapper/core.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">subprocess</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">import</span> <span class="nn">shutil</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="kn">from</span> <span class="nn">pathlib</span> <span class="kn">import</span> <span class="n">Path</span>
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="k">def</span> <span class="nf">find_binary</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="s2">&#34;&#34;&#34;找到封裝的二進位檔案&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">    <span class="c1"># 二進位通常放在套件目錄內</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="n">package_dir</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span><span class="o">.</span><span class="n">parent</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="n">binary</span> <span class="o">=</span> <span class="n">package_dir</span> <span class="o">/</span> <span class="s2">&#34;bin&#34;</span> <span class="o">/</span> <span class="s2">&#34;my_tool&#34;</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">
</span></span><span class="line"><span class="ln">12</span><span class="cl">    <span class="k">if</span> <span class="n">binary</span><span class="o">.</span><span class="n">exists</span><span class="p">():</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">        <span class="k">return</span> <span class="n">binary</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="c1"># 或者在 PATH 中尋找</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">    <span class="k">return</span> <span class="n">shutil</span><span class="o">.</span><span class="n">which</span><span class="p">(</span><span class="s2">&#34;my_tool&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="k">def</span> <span class="nf">run_tool</span><span class="p">(</span><span class="n">input_text</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="s2">&#34;&#34;&#34;呼叫封裝的工具&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">    <span class="n">binary</span> <span class="o">=</span> <span class="n">find_binary</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">21</span><span class="cl">    <span class="k">if</span> <span class="ow">not</span> <span class="n">binary</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl">        <span class="k">raise</span> <span class="ne">RuntimeError</span><span class="p">(</span><span class="s2">&#34;找不到 my_tool 二進位&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl">
</span></span><span class="line"><span class="ln">24</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">run</span><span class="p">(</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">        <span class="p">[</span><span class="nb">str</span><span class="p">(</span><span class="n">binary</span><span class="p">)],</span>
</span></span><span class="line"><span class="ln">26</span><span class="cl">        <span class="nb">input</span><span class="o">=</span><span class="n">input_text</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">        <span class="n">capture_output</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">        <span class="n">text</span><span class="o">=</span><span class="kc">True</span><span class="p">,</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">        <span class="n">check</span><span class="o">=</span><span class="kc">True</span>
</span></span><span class="line"><span class="ln">30</span><span class="cl">    <span class="p">)</span>
</span></span><span class="line"><span class="ln">31</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="o">.</span><span class="n">stdout</span></span></span></code></pre></div><h3 id="方法二ctypes--cffi">方法二：ctypes / cffi</h3>
<p>適合函式庫（.so / .dll）：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-python" data-lang="python"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c1"># my_wrapper/bindings.py</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="kn">import</span> <span class="nn">ctypes</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="kn">from</span> <span class="nn">pathlib</span> <span class="kn">import</span> <span class="n">Path</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="k">def</span> <span class="nf">load_library</span><span class="p">():</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">    <span class="s2">&#34;&#34;&#34;載入共享函式庫&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">    <span class="n">package_dir</span> <span class="o">=</span> <span class="n">Path</span><span class="p">(</span><span class="vm">__file__</span><span class="p">)</span><span class="o">.</span><span class="n">parent</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">    <span class="c1"># 根據平台選擇正確的檔案</span>
</span></span><span class="line"><span class="ln">10</span><span class="cl">    <span class="kn">import</span> <span class="nn">platform</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl">    <span class="k">if</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span> <span class="o">==</span> <span class="s2">&#34;Darwin&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl">        <span class="n">lib_name</span> <span class="o">=</span> <span class="s2">&#34;libmy_tool.dylib&#34;</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="k">elif</span> <span class="n">platform</span><span class="o">.</span><span class="n">system</span><span class="p">()</span> <span class="o">==</span> <span class="s2">&#34;Windows&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl">        <span class="n">lib_name</span> <span class="o">=</span> <span class="s2">&#34;my_tool.dll&#34;</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">    <span class="k">else</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">16</span><span class="cl">        <span class="n">lib_name</span> <span class="o">=</span> <span class="s2">&#34;libmy_tool.so&#34;</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl">
</span></span><span class="line"><span class="ln">18</span><span class="cl">    <span class="n">lib_path</span> <span class="o">=</span> <span class="n">package_dir</span> <span class="o">/</span> <span class="s2">&#34;lib&#34;</span> <span class="o">/</span> <span class="n">lib_name</span>
</span></span><span class="line"><span class="ln">19</span><span class="cl">    <span class="k">return</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">CDLL</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">lib_path</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">20</span><span class="cl">
</span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="c1"># 載入並設定函式簽名</span>
</span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="n">_lib</span> <span class="o">=</span> <span class="n">load_library</span><span class="p">()</span>
</span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="n">_lib</span><span class="o">.</span><span class="n">process_data</span><span class="o">.</span><span class="n">argtypes</span> <span class="o">=</span> <span class="p">[</span><span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="n">_lib</span><span class="o">.</span><span class="n">process_data</span><span class="o">.</span><span class="n">restype</span> <span class="o">=</span> <span class="n">ctypes</span><span class="o">.</span><span class="n">c_char_p</span>
</span></span><span class="line"><span class="ln">25</span><span class="cl">
</span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="k">def</span> <span class="nf">process_data</span><span class="p">(</span><span class="n">data</span><span class="p">:</span> <span class="nb">str</span><span class="p">)</span> <span class="o">-&gt;</span> <span class="nb">str</span><span class="p">:</span>
</span></span><span class="line"><span class="ln">27</span><span class="cl">    <span class="s2">&#34;&#34;&#34;Python 友善的介面&#34;&#34;&#34;</span>
</span></span><span class="line"><span class="ln">28</span><span class="cl">    <span class="n">result</span> <span class="o">=</span> <span class="n">_lib</span><span class="o">.</span><span class="n">process_data</span><span class="p">(</span><span class="n">data</span><span class="o">.</span><span class="n">encode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">))</span>
</span></span><span class="line"><span class="ln">29</span><span class="cl">    <span class="k">return</span> <span class="n">result</span><span class="o">.</span><span class="n">decode</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span></span></span></code></pre></div><h3 id="方法三使用專門工具">方法三：使用專門工具</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">推薦工具：
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── PyOxidizer：打包 Python + Rust
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── Briefcase：跨平台打包
</span></span><span class="line"><span class="ln">4</span><span class="cl">├── Nuitka：Python → 原生編譯
</span></span><span class="line"><span class="ln">5</span><span class="cl">└── 自訂 GitHub Actions：建構多平台 wheel</span></span></code></pre></div><hr>
<h2 id="打包建立-wheel">【打包】建立 wheel</h2>
<h3 id="專案結構">專案結構</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">my_package/
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">├── pyproject.toml
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├── src/
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">│   └── my_package/
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">│       ├── __init__.py
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">│       ├── core.py          # Python 封裝
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">│       └── bin/             # 預編譯二進位
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">│           ├── my_tool-linux-x64
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">│           ├── my_tool-darwin-arm64
</span></span><span class="line"><span class="ln">10</span><span class="cl">│           └── my_tool-windows-x64.exe
</span></span><span class="line"><span class="ln">11</span><span class="cl">└── scripts/
</span></span><span class="line"><span class="ln">12</span><span class="cl">    └── build_binaries.sh    # 建構腳本</span></span></code></pre></div><h3 id="pyprojecttoml-設定">pyproject.toml 設定</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-toml" data-lang="toml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="p">[</span><span class="nx">build-system</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="nx">requires</span> <span class="p">=</span> <span class="p">[</span><span class="s2">&#34;hatchling&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="nx">build-backend</span> <span class="p">=</span> <span class="s2">&#34;hatchling.build&#34;</span>
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">
</span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="p">[</span><span class="nx">project</span><span class="p">]</span>
</span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="nx">name</span> <span class="p">=</span> <span class="s2">&#34;my-package&#34;</span>
</span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="nx">version</span> <span class="p">=</span> <span class="s2">&#34;0.1.0&#34;</span>
</span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="nx">description</span> <span class="p">=</span> <span class="s2">&#34;Python wrapper for my_tool&#34;</span>
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">
</span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="p">[</span><span class="nx">tool</span><span class="p">.</span><span class="nx">hatch</span><span class="p">.</span><span class="nx">build</span><span class="p">.</span><span class="nx">targets</span><span class="p">.</span><span class="nx">wheel</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="c"># 包含二進位檔案</span>
</span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="nx">include</span> <span class="p">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="ln">13</span><span class="cl">    <span class="s2">&#34;src/my_package/bin/*&#34;</span>
</span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="p">]</span>
</span></span><span class="line"><span class="ln">15</span><span class="cl">
</span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="c"># 設定平台特定的 wheel</span>
</span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="p">[</span><span class="nx">tool</span><span class="p">.</span><span class="nx">hatch</span><span class="p">.</span><span class="nx">build</span><span class="p">.</span><span class="nx">targets</span><span class="p">.</span><span class="nx">wheel</span><span class="p">.</span><span class="nx">hooks</span><span class="p">.</span><span class="nx">custom</span><span class="p">]</span>
</span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="c"># 自訂 hook 來處理平台特定二進位</span></span></span></code></pre></div><h3 id="github-actions-範例">GitHub Actions 範例</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="ln"> 1</span><span class="cl"><span class="c"># .github/workflows/build.yml</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 2</span><span class="cl"><span class="w"></span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Build wheels</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 3</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 4</span><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">push, release]</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 5</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln"> 6</span><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 7</span><span class="cl"><span class="w">  </span><span class="nt">build</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 8</span><span class="cl"><span class="w">    </span><span class="nt">strategy</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln"> 9</span><span class="cl"><span class="w">      </span><span class="nt">matrix</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">10</span><span class="cl"><span class="w">        </span><span class="nt">os</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">ubuntu-latest, macos-latest, windows-latest]</span><span class="w">
</span></span></span><span class="line"><span class="ln">11</span><span class="cl"><span class="w">        </span><span class="nt">arch</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">x64, arm64]</span><span class="w">
</span></span></span><span class="line"><span class="ln">12</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">13</span><span class="cl"><span class="w">    </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">${{ matrix.os }}</span><span class="w">
</span></span></span><span class="line"><span class="ln">14</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">15</span><span class="cl"><span class="w">    </span><span class="nt">steps</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">16</span><span class="cl"><span class="w">      </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v4</span><span class="w">
</span></span></span><span class="line"><span class="ln">17</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">18</span><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Build binary</span><span class="w">
</span></span></span><span class="line"><span class="ln">19</span><span class="cl"><span class="w">        </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="ln">20</span><span class="cl"><span class="sd">          # 根據目標平台建構二進位
</span></span></span><span class="line"><span class="ln">21</span><span class="cl"><span class="sd">          ./scripts/build_binary.sh ${{ matrix.arch }}</span><span class="w">
</span></span></span><span class="line"><span class="ln">22</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">23</span><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Build wheel</span><span class="w">
</span></span></span><span class="line"><span class="ln">24</span><span class="cl"><span class="w">        </span><span class="nt">run</span><span class="p">:</span><span class="w"> </span><span class="p">|</span><span class="sd">
</span></span></span><span class="line"><span class="ln">25</span><span class="cl"><span class="sd">          pip install build
</span></span></span><span class="line"><span class="ln">26</span><span class="cl"><span class="sd">          python -m build --wheel</span><span class="w">
</span></span></span><span class="line"><span class="ln">27</span><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="ln">28</span><span class="cl"><span class="w">      </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">Upload wheel</span><span class="w">
</span></span></span><span class="line"><span class="ln">29</span><span class="cl"><span class="w">        </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/upload-artifact@v4</span><span class="w">
</span></span></span><span class="line"><span class="ln">30</span><span class="cl"><span class="w">        </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="ln">31</span><span class="cl"><span class="w">          </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">wheel-${{ matrix.os }}-${{ matrix.arch }}</span><span class="w">
</span></span></span><span class="line"><span class="ln">32</span><span class="cl"><span class="w">          </span><span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">dist/*.whl</span></span></span></code></pre></div><hr>
<h2 id="案例研究beautiful-mermaid-py">【案例研究】beautiful-mermaid-py</h2>
<h3 id="背景">背景</h3>
<p>將 Mermaid 圖表轉換為 ASCII 藝術的工具，存在多種實現：</p>
<table>
  <thead>
      <tr>
          <th>專案</th>
          <th>語言</th>
          <th>實現方式</th>
          <th>圖表支援</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>mermaid-ascii</td>
          <td>Go</td>
          <td>原創實現</td>
          <td>2 種</td>
      </tr>
      <tr>
          <td>beautiful-mermaid</td>
          <td>TypeScript</td>
          <td>從 Go 移植並擴展</td>
          <td>5 種</td>
      </tr>
      <tr>
          <td>beautiful-mermaid-py</td>
          <td>Python</td>
          <td>從 TypeScript 移植</td>
          <td>5 種</td>
      </tr>
      <tr>
          <td>osl-packages/mermaid-ascii</td>
          <td>Python</td>
          <td>封裝 Go 二進位</td>
          <td>2 種</td>
      </tr>
  </tbody>
</table>
<h3 id="兩種-python-方案比較">兩種 Python 方案比較</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">方案 A：封裝 Go 二進位（osl-packages）
</span></span><span class="line"><span class="ln">2</span><span class="cl">├── 優點：效能較好、維護成本低
</span></span><span class="line"><span class="ln">3</span><span class="cl">├── 缺點：平台依賴、無法修改邏輯
</span></span><span class="line"><span class="ln">4</span><span class="cl">└── 適合：追求效能、不需自訂
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl">方案 B：純 Python 移植（beautiful-mermaid-py）
</span></span><span class="line"><span class="ln">7</span><span class="cl">├── 優點：無依賴、可自訂、跨平台
</span></span><span class="line"><span class="ln">8</span><span class="cl">├── 缺點：效能略低（但對此任務足夠）
</span></span><span class="line"><span class="ln">9</span><span class="cl">└── 適合：需要修改、追求簡潔</span></span></code></pre></div><h3 id="決策分析">決策分析</h3>
<p>對於 Mermaid ASCII 渲染這個需求：</p>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">效能需求：低（渲染一次圖表不需要毫秒級優化）
</span></span><span class="line"><span class="ln">2</span><span class="cl">修改需求：可能（未來可能想客製化輸出格式）
</span></span><span class="line"><span class="ln">3</span><span class="cl">平台多樣性：高（不同開發環境）
</span></span><span class="line"><span class="ln">4</span><span class="cl">維護成本：純 Python 更低
</span></span><span class="line"><span class="ln">5</span><span class="cl">
</span></span><span class="line"><span class="ln">6</span><span class="cl">結論：對於這個場景，純 Python 是更好的選擇</span></span></code></pre></div><hr>
<h2 id="總結">總結</h2>
<h3 id="何時封裝二進位">何時封裝二進位</h3>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln"> 1</span><span class="cl">適合封裝二進位：
</span></span><span class="line"><span class="ln"> 2</span><span class="cl">├── 效能關鍵的運算（加密、ML、圖像處理）
</span></span><span class="line"><span class="ln"> 3</span><span class="cl">├── 已有成熟的非 Python 實現
</span></span><span class="line"><span class="ln"> 4</span><span class="cl">├── 需要系統級別的操作
</span></span><span class="line"><span class="ln"> 5</span><span class="cl">└── 安全性要求使用審計過的程式碼
</span></span><span class="line"><span class="ln"> 6</span><span class="cl">
</span></span><span class="line"><span class="ln"> 7</span><span class="cl">不適合封裝二進位：
</span></span><span class="line"><span class="ln"> 8</span><span class="cl">├── 簡單的文字處理或資料轉換
</span></span><span class="line"><span class="ln"> 9</span><span class="cl">├── 需要頻繁修改邏輯的功能
</span></span><span class="line"><span class="ln">10</span><span class="cl">├── 追求最大可移植性的工具
</span></span><span class="line"><span class="ln">11</span><span class="cl">└── 功能用純 Python 就能達到足夠效能</span></span></code></pre></div><h3 id="架構選擇原則">架構選擇原則</h3>
<ol>
<li><strong>效能驅動</strong>：只有當效能是瓶頸時才考慮封裝二進位</li>
<li><strong>重用優先</strong>：有成熟實現時考慮封裝，否則考慮純 Python</li>
<li><strong>維護成本</strong>：評估長期維護的複雜度</li>
<li><strong>團隊技能</strong>：選擇團隊能夠維護的方案</li>
</ol>
<hr>
<h2 id="延伸閱讀">延伸閱讀</h2>
<ul>
<li><a href="https://packaging.python.org/en/latest/guides/packaging-binary-extensions/">Python Packaging Guide - Binary Extensions</a></li>
<li><a href="https://github.com/pypa/manylinux">manylinux 標準</a></li>
<li><a href="https://pyoxidizer.readthedocs.io/">PyOxidizer 文件</a></li>
<li><a href="/blog/python-advanced/05-c-extensions/" data-link-title="模組五：用 C 擴展 Python" data-link-desc="學習使用 ctypes、cffi、Cython、pybind11 擴展 Python">模組四：用 C 擴展 Python</a> - 另一種整合原生程式碼的方式</li>
</ul>
<hr>
<p><em>上一章：<a href="/blog/python-advanced/07-packaging/best-practices/" data-link-title="6.4 套件維護最佳實踐" data-link-desc="長期維護 Python 套件的最佳實踐">套件維護最佳實踐</a></em>
<em>下一模組：<a href="/blog/python-advanced/08-practical-optimization/" data-link-title="模組八：實戰效能優化" data-link-desc="將入門系列的並行處理與效能優化知識應用於真實系統">模組七：實戰效能優化</a></em></p>
]]></content:encoded></item><item><title>模組五：用 C 擴展 Python</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/</link><pubDate>Tue, 20 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/</guid><description>&lt;p>本模組介紹如何使用 C/C++ 擴展 Python，提升效能或整合現有的 C 函式庫。&lt;/p>
&lt;h2 id="為什麼學習-c-擴展">為什麼學習 C 擴展？&lt;/h2>
&lt;ul>
&lt;li>&lt;strong>效能極致&lt;/strong>：當 Python 太慢時的解決方案&lt;/li>
&lt;li>&lt;strong>整合現有庫&lt;/strong>：呼叫 C/C++ 函式庫&lt;/li>
&lt;li>&lt;strong>理解生態系&lt;/strong>：NumPy、SciPy 等高效能套件的實現原理&lt;/li>
&lt;/ul>
&lt;h2 id="章節列表">章節列表&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>章節&lt;/th>
 &lt;th>主題&lt;/th>
 &lt;th>關鍵收穫&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/ctypes-cffi/" data-link-title="4.1 ctypes 與 cffi：動態綁定" data-link-desc="使用 ctypes 和 cffi 呼叫 C 函式庫">5.1&lt;/a>&lt;/td>
 &lt;td>ctypes 與 cffi&lt;/td>
 &lt;td>動態綁定 C 函式庫&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/cython/" data-link-title="4.2 Cython：Python 語法的 C 速度" data-link-desc="使用 Cython 加速 Python 程式碼">5.2&lt;/a>&lt;/td>
 &lt;td>Cython&lt;/td>
 &lt;td>Python 語法的 C 速度&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/pybind11/" data-link-title="4.3 pybind11：現代 C&amp;#43;&amp;#43; 綁定" data-link-desc="使用 pybind11 建立 Python 與 C&amp;#43;&amp;#43; 的綁定">5.3&lt;/a>&lt;/td>
 &lt;td>pybind11&lt;/td>
 &lt;td>現代 C++ 綁定&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/when-to-use/" data-link-title="4.4 選擇指南與效能比較" data-link-desc="比較不同 C 擴展工具的適用場景">5.4&lt;/a>&lt;/td>
 &lt;td>選擇指南&lt;/td>
 &lt;td>工具比較與決策&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="工具選擇快速指南">工具選擇快速指南&lt;/h2>





&lt;div class="highlight">&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="ln">1&lt;/span>&lt;span class="cl">沒有原始碼 ──────→ ctypes / cffi
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">2&lt;/span>&lt;span class="cl">純 C 函式庫 ─────→ cffi 或 Cython
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">3&lt;/span>&lt;span class="cl">C++ 函式庫 ──────→ pybind11
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="ln">4&lt;/span>&lt;span class="cl">優化現有 Python ─→ Cython&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="先備知識">先備知識&lt;/h2>
&lt;ul>
&lt;li>進階系列 &lt;a href="https://tarrragon.github.io/blog/python-advanced/04-cpython-internals/" data-link-title="模組四：CPython 內部機制" data-link-desc="深入 CPython 直譯器，理解 Python 如何運作">模組四：CPython 內部機制&lt;/a>&lt;/li>
&lt;li>基本的 C 語言知識（指標、結構體、記憶體管理）&lt;/li>
&lt;/ul>
&lt;h2 id="學習時間">學習時間&lt;/h2>
&lt;p>每章節約 45-60 分鐘，全模組約 3-4 小時&lt;/p>
&lt;hr>
&lt;p>&lt;em>上一模組：&lt;a href="https://tarrragon.github.io/blog/python-advanced/04-cpython-internals/" data-link-title="模組四：CPython 內部機制" data-link-desc="深入 CPython 直譯器，理解 Python 如何運作">模組四：CPython 內部機制&lt;/a>&lt;/em>
&lt;em>下一模組：&lt;a href="https://tarrragon.github.io/blog/python-advanced/06-rust-extensions/" data-link-title="模組六：用 Rust 擴展 Python" data-link-desc="學習使用 PyO3 和 Maturin 用 Rust 擴展 Python">模組六：用 Rust 擴展 Python&lt;/a>&lt;/em>&lt;/p></description><content:encoded><![CDATA[<p>本模組介紹如何使用 C/C++ 擴展 Python，提升效能或整合現有的 C 函式庫。</p>
<h2 id="為什麼學習-c-擴展">為什麼學習 C 擴展？</h2>
<ul>
<li><strong>效能極致</strong>：當 Python 太慢時的解決方案</li>
<li><strong>整合現有庫</strong>：呼叫 C/C++ 函式庫</li>
<li><strong>理解生態系</strong>：NumPy、SciPy 等高效能套件的實現原理</li>
</ul>
<h2 id="章節列表">章節列表</h2>
<table>
  <thead>
      <tr>
          <th>章節</th>
          <th>主題</th>
          <th>關鍵收穫</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/python-advanced/05-c-extensions/ctypes-cffi/" data-link-title="4.1 ctypes 與 cffi：動態綁定" data-link-desc="使用 ctypes 和 cffi 呼叫 C 函式庫">5.1</a></td>
          <td>ctypes 與 cffi</td>
          <td>動態綁定 C 函式庫</td>
      </tr>
      <tr>
          <td><a href="/blog/python-advanced/05-c-extensions/cython/" data-link-title="4.2 Cython：Python 語法的 C 速度" data-link-desc="使用 Cython 加速 Python 程式碼">5.2</a></td>
          <td>Cython</td>
          <td>Python 語法的 C 速度</td>
      </tr>
      <tr>
          <td><a href="/blog/python-advanced/05-c-extensions/pybind11/" data-link-title="4.3 pybind11：現代 C&#43;&#43; 綁定" data-link-desc="使用 pybind11 建立 Python 與 C&#43;&#43; 的綁定">5.3</a></td>
          <td>pybind11</td>
          <td>現代 C++ 綁定</td>
      </tr>
      <tr>
          <td><a href="/blog/python-advanced/05-c-extensions/when-to-use/" data-link-title="4.4 選擇指南與效能比較" data-link-desc="比較不同 C 擴展工具的適用場景">5.4</a></td>
          <td>選擇指南</td>
          <td>工具比較與決策</td>
      </tr>
  </tbody>
</table>
<h2 id="工具選擇快速指南">工具選擇快速指南</h2>





<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="ln">1</span><span class="cl">沒有原始碼 ──────→ ctypes / cffi
</span></span><span class="line"><span class="ln">2</span><span class="cl">純 C 函式庫 ─────→ cffi 或 Cython
</span></span><span class="line"><span class="ln">3</span><span class="cl">C++ 函式庫 ──────→ pybind11
</span></span><span class="line"><span class="ln">4</span><span class="cl">優化現有 Python ─→ Cython</span></span></code></pre></div><h2 id="先備知識">先備知識</h2>
<ul>
<li>進階系列 <a href="/blog/python-advanced/04-cpython-internals/" data-link-title="模組四：CPython 內部機制" data-link-desc="深入 CPython 直譯器，理解 Python 如何運作">模組四：CPython 內部機制</a></li>
<li>基本的 C 語言知識（指標、結構體、記憶體管理）</li>
</ul>
<h2 id="學習時間">學習時間</h2>
<p>每章節約 45-60 分鐘，全模組約 3-4 小時</p>
<hr>
<p><em>上一模組：<a href="/blog/python-advanced/04-cpython-internals/" data-link-title="模組四：CPython 內部機制" data-link-desc="深入 CPython 直譯器，理解 Python 如何運作">模組四：CPython 內部機制</a></em>
<em>下一模組：<a href="/blog/python-advanced/06-rust-extensions/" data-link-title="模組六：用 Rust 擴展 Python" data-link-desc="學習使用 PyO3 和 Maturin 用 Rust 擴展 Python">模組六：用 Rust 擴展 Python</a></em></p>
]]></content:encoded></item><item><title>案例研究</title><link>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/</link><pubDate>Wed, 21 Jan 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/</guid><description>&lt;p>本節收錄基於 &lt;code>.claude/lib&lt;/code> 實際程式碼的案例研究，展示如何用 Cython 加速 Python 程式碼。&lt;/p>
&lt;h2 id="案例列表">案例列表&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>案例&lt;/th>
 &lt;th>素材&lt;/th>
 &lt;th>學習重點&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/cython-markdown/" data-link-title="案例：Cython 加速 Markdown 解析" data-link-desc="用 Cython 加速 Markdown 連結解析器，比較純 Python 與 Cython 的效能差異">Cython 加速 Markdown 解析&lt;/a>&lt;/td>
 &lt;td>markdown_link_checker.py&lt;/td>
 &lt;td>Cython 基礎、型別宣告、效能比較&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;a href="https://tarrragon.github.io/blog/python-advanced/05-c-extensions/case-studies/ctypes-system-call/" data-link-title="案例：使用 ctypes 呼叫系統 API" data-link-desc="透過 ctypes 直接呼叫 C 函式庫的系統函式，實現 Python 標準庫未提供的功能">使用 ctypes 呼叫系統 API&lt;/a>&lt;/td>
 &lt;td>系統 API&lt;/td>
 &lt;td>ctypes 實戰、跨平台、效能比較&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="學習路徑">學習路徑&lt;/h2>
&lt;p>建議先完成本模組的理論章節，再閱讀案例研究：&lt;/p>
&lt;ol>
&lt;li>理解 Python/C API 基礎&lt;/li>
&lt;li>學習 Cython 語法&lt;/li>
&lt;li>通過案例實踐加速技巧&lt;/li>
&lt;/ol></description><content:encoded><![CDATA[<p>本節收錄基於 <code>.claude/lib</code> 實際程式碼的案例研究，展示如何用 Cython 加速 Python 程式碼。</p>
<h2 id="案例列表">案例列表</h2>
<table>
  <thead>
      <tr>
          <th>案例</th>
          <th>素材</th>
          <th>學習重點</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td><a href="/blog/python-advanced/05-c-extensions/case-studies/cython-markdown/" data-link-title="案例：Cython 加速 Markdown 解析" data-link-desc="用 Cython 加速 Markdown 連結解析器，比較純 Python 與 Cython 的效能差異">Cython 加速 Markdown 解析</a></td>
          <td>markdown_link_checker.py</td>
          <td>Cython 基礎、型別宣告、效能比較</td>
      </tr>
      <tr>
          <td><a href="/blog/python-advanced/05-c-extensions/case-studies/ctypes-system-call/" data-link-title="案例：使用 ctypes 呼叫系統 API" data-link-desc="透過 ctypes 直接呼叫 C 函式庫的系統函式，實現 Python 標準庫未提供的功能">使用 ctypes 呼叫系統 API</a></td>
          <td>系統 API</td>
          <td>ctypes 實戰、跨平台、效能比較</td>
      </tr>
  </tbody>
</table>
<h2 id="學習路徑">學習路徑</h2>
<p>建議先完成本模組的理論章節，再閱讀案例研究：</p>
<ol>
<li>理解 Python/C API 基礎</li>
<li>學習 Cython 語法</li>
<li>通過案例實踐加速技巧</li>
</ol>
]]></content:encoded></item></channel></rss>