# 調用 C 庫函數
> 原文: [http://docs.cython.org/en/latest/src/tutorial/external.html](http://docs.cython.org/en/latest/src/tutorial/external.html)
本教程簡要介紹了從 Cython 代碼調用 C 庫函數時需要了解的內容。有關使用外部 C 庫,包裝它們和處理錯誤的更長更全面的教程,請參閱 [使用 C 庫](clibraries.html) 。
為簡單起見,讓我們從標準 C 庫中的函數開始。這不會為您的代碼添加任何依賴項,并且它還具有 Cython 已經為您定義了許多此類函數的額外優勢。所以你可以直接使用它們。
例如,假設您需要一種低級方法來解析`char*`值中的數字。您可以使用`stdlib.h`頭文件定義的`atoi()`功能。這可以按如下方式完成:
```py
from libc.stdlib cimport atoi
cdef parse_charptr_to_py_int(char* s):
assert s is not NULL, "byte string value is NULL"
return atoi(s) # note: atoi() has no error detection!
```
您可以在 Cython 的源代碼包 [Cython / Includes /](https://github.com/cython/cython/tree/master/Cython/Includes) 中找到這些標準 cimport 文件的完整列表。它們存儲在`.pxd`文件中,這是提供可以在模塊之間共享的可重用 Cython 聲明的標準方法(參見 [在 Cython 模塊之間共享聲明](../userguide/sharing_declarations.html#sharing-declarations) )。
Cython 還為 CPython 的 C-API 提供了一整套聲明。例如,要在 C 編譯時測試您的代碼正在編譯的 CPython 版本,您可以這樣做:
```py
from cpython.version cimport PY_VERSION_HEX
# Python version >= 3.2 final ?
print(PY_VERSION_HEX >= 0x030200F0)
```
Cython 還提供 C 數學庫的聲明:
```py
from libc.math cimport sin
cdef double f(double x):
return sin(x * x)
```
## 動態鏈接
libc 數學庫的特殊之處在于它在某些類 Unix 系統(如 Linux)上沒有默認鏈接。除了導入聲明之外,還必須將構建系統配置為鏈接到共享庫`m`。對于 distutils,將它添加到`Extension()`設置的`libraries`參數就足夠了:
```py
from distutils.core import setup
from distutils.extension import Extension
from Cython.Build import cythonize
ext_modules = [
Extension("demo",
sources=["demo.pyx"],
libraries=["m"] # Unix-like specific
)
]
setup(name="Demos",
ext_modules=cythonize(ext_modules))
```
## 外部聲明
如果要訪問 Cython 未提供即用型聲明的 C 代碼,則必須自行聲明。例如,上面的`sin()`函數定義如下:
```py
cdef extern from "math.h":
double sin(double x)
```
這聲明了`sin()`函數,使其可用于 Cython 代碼并指示 Cython 生成包含`math.h`頭文件的 C 代碼。 C 編譯器將在編譯時在`math.h`中看到原始聲明,但 Cython 不解析“math.h”并需要單獨的定義。
就像數學庫中的`sin()`函數一樣,只要 Cython 生成的模塊與共享庫或靜態庫正確鏈接,就可以聲明并調用任何 C 庫。
請注意,通過將其聲明為`cpdef`,可以輕松地從 Cython 模塊導出外部 C 函數。這會為它生成一個 Python 包裝器并將其添加到模塊 dict 中。這是一個 Cython 模塊,可以直接訪問 Python 代碼的 C `sin()`函數:
```py
"""
>>> sin(0)
0.0
"""
cdef extern from "math.h":
cpdef double sin(double x)
```
當此聲明出現在屬于 Cython 模塊的`.pxd`文件中時(即具有相同名稱的 [在 Cython 模塊之間共享聲明](../userguide/sharing_declarations.html#sharing-declarations) ),會得到相同的結果。這允許 C 聲明在其他 Cython 模塊中重用,同時仍然在此特定模塊中提供自動生成的 Python 包裝器。
## 命名參數
C 和 Cython 都支持沒有參數名稱的簽名聲明,如下所示:
```py
cdef extern from "string.h":
char* strstr(const char*, const char*)
```
但是,這會阻止 Cython 代碼使用關鍵字參數調用它。因此,最好像這樣編寫聲明:
```py
cdef extern from "string.h":
char* strstr(const char *haystack, const char *needle)
```
您現在可以清楚地說明兩個參數中的哪一個在您的調用中執行了哪些操作,從而避免了任何歧義并且通常使您的代碼更具可讀性:
```py
cdef extern from "string.h":
char* strstr(const char *haystack, const char *needle)
cdef char* data = "hfvcakdfagbcffvschvxcdfgccbcfhvgcsnfxjh"
cdef char* pos = strstr(needle='akd', haystack=data)
print(pos is not NULL)
```
請注意,稍后更改現有參數名稱是向后不兼容的 API 修改,就像 Python 代碼一樣。因此,如果您為外部 C 或 C ++函數提供自己的聲明,那么通常需要額外的工作來選擇其參數的名稱。
- Cython 3.0 中文文檔
- 入門
- Cython - 概述
- 安裝 Cython
- 構建 Cython 代碼
- 通過靜態類型更快的代碼
- Tutorials
- 基礎教程
- 調用 C 函數
- 使用 C 庫
- 擴展類型(又名.cdef 類)
- pxd 文件
- Caveats
- Profiling
- Unicode 和傳遞字符串
- 內存分配
- 純 Python 模式
- 使用 NumPy
- 使用 Python 數組
- 進一步閱讀
- 相關工作
- 附錄:在 Windows 上安裝 MinGW
- 用戶指南
- 語言基礎
- 擴展類型
- 擴展類型的特殊方法
- 在 Cython 模塊之間共享聲明
- 與外部 C 代碼連接
- 源文件和編譯
- 早期綁定速度
- 在 Cython 中使用 C ++
- 融合類型(模板)
- 將 Cython 代碼移植到 PyPy
- Limitations
- Cython 和 Pyrex 之間的區別
- 鍵入的內存視圖
- 實現緩沖協議
- 使用并行性
- 調試你的 Cython 程序
- 用于 NumPy 用戶的 Cython
- Pythran 作為 Numpy 后端