簡介¶
對於 Python 的應用程式開發介面使得 C 和 C++ 開發者能夠在各種層級存取 Python 直譯器。該 API 同樣可用於 C++,但為簡潔起見,通常將其稱為 Python/C API。使用 Python/C API 有兩個不同的原因,第一個是為特定目的來編寫擴充模組;這些是擴充 Python 直譯器的 C 模組,這可能是最常見的用法。第二個原因是在更大的應用程式中將 Python 作為零件使用;這種技術通常在應用程式中稱為 embedding(嵌入式)Python。
編寫擴充模組是一個相對容易理解的過程,其中「食譜 (cookbook)」方法很有效。有幾種工具可以在一定程度上自動化該過程,儘管人們從早期就將 Python 嵌入到其他應用程式中,但嵌入 Python 的過程並不像編寫擴充那樣簡單。
不論你是嵌入還是擴充 Python,許多 API 函式都是很有用的;此外,大多數嵌入 Python 的應用程式也需要提供自訂擴充模組,因此在嘗試將 Python 嵌入實際應用程式之前熟悉編寫擴充可能是個好主意。
語言版本相容性¶
Python 的 C API 與 C11 和 C++11 版本的 C 和 C++ 相容。
This is a lower limit: the C API does not require features from later C/C++ versions. You do not need to enable your compiler's "c11 mode".
編寫標準¶
如果你正在編寫要引入於 CPython 中的 C 程式碼,你必須遵循 PEP 7 中定義的指南和標準。無論你貢獻的 Python 版本如何,這些指南都適用。對於你自己的第三方擴充模組,則不必遵循這些約定,除非你希望最終將它們貢獻給 Python。
引入檔案 (include files)¶
使用 Python/C API 所需的所有函式、型別和巨集的定義都透過以下這幾行來在你的程式碼中引入:
#define PY_SSIZE_T_CLEAN
#include <Python.h>
這意味著會引入以下標準標頭:<stdio.h>、<string.h>、<errno.h>、<limits.h>、<assert.h> 和 <stdlib.h>(如果可用)。
備註
由於 Python 可能會定義一些會影響某些系統上標準標頭檔的預處理器 (pre-processor),因此你必須在引入任何標準標頭檔之前引入 Python.h。
建議在引入 Python.h 之前都要定義 PY_SSIZE_T_CLEAN。有關此巨集的說明,請參閱剖析引數與建置數值。
所有定義於 Python.h 中且使用者可見的名稱(另外透過標準標頭檔引入的除外)都具有 Py 或 _Py 前綴。以 _Py 開頭的名稱供 Python 實作內部使用,擴充編寫者不應使用。結構成員名稱沒有保留前綴。
備註
使用者程式碼不應定義任何以 Py 或 _Py 開頭的名稱。這會讓讀者感到困惑,並危及使用者程式碼在未來 Python 版本上的可移植性,這些版本可能會定義以這些前綴之一開頭的其他名稱。
標頭檔通常隨 Python 一起安裝。在 Unix 上它們位於目錄 prefix/include/pythonversion/ 和 exec_prefix/include/pythonversion/,其中 prefix 和 exec_prefix 由 Python 的 configure 腳本的相應參數定義,version 是 '%d.%d' % sys.version_info[:2]。在 Windows 上,標頭安裝在 prefix/include 中,其中 prefix 是指定給安裝程式 (installer) 用的安裝目錄。
要引入標頭,請將兩個(如果不同)目錄放在編譯器的引入搜尋路徑 (search path) 中。不要將父目錄放在搜尋路徑上,然後使用 #include <pythonX.Y/Python.h>;這會在多平台建置上壞掉,因為 prefix 下獨立於平台的標頭包括來自 exec_prefix 的平台特定標頭。
C++ 使用者應注意,儘管 API 完全使用 C 來定義,但標頭檔適當地將入口點聲明為 extern "C"。因此,無需執行任何特殊操作即可使用 C++ 中的 API。
有用的巨集¶
Python 標頭檔中定義了幾個有用的巨集,大多被定義在它們有用的地方附近(例如 Py_RETURN_NONE、PyMODINIT_FUNC),其他是更通用的工具程式。以下並不一定是完整的列表。
-
Py_CAN_START_THREADS¶
如果有定義此巨集,則目前系統就能夠啟動執行緒。
Currently, all systems supported by CPython (per PEP 11), with the exception of some WebAssembly platforms, support starting threads.
在 3.13 版被加入.
-
Py_GETENV(s)¶
類似於
getenv(s),但如果在命令列上傳遞了-E則回傳NULL(請見PyConfig.use_environment)。
文件字串巨集¶
-
PyDoc_STRVAR(name, str)¶
建立一個名為 name 的變數,可以在文件字串中使用。如果 Python 是在沒有文件字串的情況下建置 (
--without-doc-strings),則該值將為空字串。範例:
PyDoc_STRVAR(pop_doc, "Remove and return the rightmost element."); static PyMethodDef deque_methods[] = { // ... {"pop", (PyCFunction)deque_pop, METH_NOARGS, pop_doc}, // ... }
Expands to
PyDoc_VAR(name) = PyDoc_STR(str).
-
PyDoc_STR(str)¶
擴展至給定的輸入字串,或如果文件字串被禁用 (
--without-doc-strings) 則建立空字串。範例:
static PyMethodDef pysqlite_row_methods[] = { {"keys", (PyCFunction)pysqlite_row_keys, METH_NOARGS, PyDoc_STR("Returns the keys of the row.")}, {NULL, NULL} };
-
PyDoc_VAR(name)¶
Declares a static character array variable with the given name. Expands to
static const char name[]範例:
PyDoc_VAR(python_doc) = PyDoc_STR( "A genus of constricting snakes in the Pythonidae family native " "to the tropics and subtropics of the Eastern Hemisphere.");
General utility macros¶
The following macros are for common tasks not specific to Python.
-
Py_UNUSED(arg)¶
將此用於函式定義中未使用的參數以消除編譯器警告。例如:
int func(int a, int Py_UNUSED(b)) { return a; }。在 3.4 版被加入.
-
Py_GCC_ATTRIBUTE(name)¶
Use a GCC attribute name, hiding it from compilers that don't support GCC attributes (such as MSVC).
This expands to
__attribute__((name))on a GCC compiler, and expands to nothing on compilers that don't support GCC attributes.
Numeric utilities¶
-
Py_ABS(x)¶
回傳
x的絕對值。The argument may be evaluated more than once. Consequently, do not pass an expression with side-effects directly to this macro.
If the result cannot be represented (for example, if
xhasINT_MINvalue for int type), the behavior is undefined.Corresponds roughly to
((x) < 0 ? -(x) : (x))在 3.3 版被加入.
-
Py_MAX(x, y)¶
-
Py_MIN(x, y)¶
Return the larger or smaller of the arguments, respectively.
Any arguments may be evaluated more than once. Consequently, do not pass an expression with side-effects directly to this macro.
Py_MAXcorresponds roughly to(((x) > (y)) ? (x) : (y)).在 3.3 版被加入.
-
Py_ARITHMETIC_RIGHT_SHIFT(type, integer, positions)¶
Similar to
integer >> positions, but forces sign extension, as the C standard does not define whether a right-shift of a signed integer will perform sign extension or a zero-fill.integer should be any signed integer type. positions is the number of positions to shift to the right.
Both integer and positions can be evaluated more than once; consequently, avoid directly passing a function call or some other operation with side-effects to this macro. Instead, store the result as a variable and then pass it.
type is unused and only kept for backwards compatibility. Historically, type was used to cast integer.
在 3.1 版的變更: This macro is now valid for all signed integer types, not just those for which
unsigned typeis legal. As a result, type is no longer used.
-
Py_CHARMASK(c)¶
引數必須是 [-128, 127] 或 [0, 255] 範圍內的字元或整數。這個巨集會將
c轉換為unsigned char並回傳。
Assertion utilities¶
-
Py_UNREACHABLE()¶
當你的設計中有無法達到的程式碼路徑時,請使用此選項。例如在
case語句已涵蓋了所有可能值的switch陳述式中的default:子句。在你可能想要呼叫assert(0)或abort()的地方使用它。在發布模式 (release mode) 下,巨集幫助編譯器最佳化程式碼,並避免有關無法存取程式碼的警告。例如該巨集是在發布模式下於 GCC 使用
__builtin_unreachable()來實作。In debug mode, and on unsupported compilers, the macro expands to a call to
Py_FatalError().Py_UNREACHABLE()的一個用途是,在對一個永不回傳但並未聲明為_Noreturn的函式之呼叫後使用。如果程式碼路徑是極不可能但在特殊情況下可以到達,則不得使用此巨集。例如在低記憶體條件下或系統呼叫回傳了超出預期範圍的值。在這種情況下,最好將錯誤回報給呼叫者。如果無法回報錯誤則可以使用
Py_FatalError()。在 3.7 版被加入.
-
Py_SAFE_DOWNCAST(value, larger, smaller)¶
Cast value to type smaller from type larger, validating that no information was lost.
On release builds of Python, this is roughly equivalent to
((smaller) value)(in C++,static_cast<smaller>(value)will be used instead).On debug builds (implying that
Py_DEBUGis defined), this asserts that no information was lost with the cast from larger to smaller.value, larger, and smaller may all be evaluated more than once in the expression; consequently, do not pass an expression with side-effects directly to this macro.
-
Py_BUILD_ASSERT(cond)¶
Asserts a compile-time condition cond, as a statement. The build will fail if the condition is false or cannot be evaluated at compile time.
Corresponds roughly to
static_assert(cond)on C23 and above.範例:
Py_BUILD_ASSERT(sizeof(PyTime_t) == sizeof(int64_t));
在 3.3 版被加入.
-
Py_BUILD_ASSERT_EXPR(cond)¶
Asserts a compile-time condition cond, as an expression that evaluates to
0. The build will fail if the condition is false or cannot be evaluated at compile time.範例:
#define foo_to_char(foo) \ ((char *)(foo) + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0))
在 3.3 版被加入.
Type size utilities¶
-
Py_ARRAY_LENGTH(array)¶
Compute the length of a statically allocated C array at compile time.
The array argument must be a C array with a size known at compile time. Passing an array with an unknown size, such as a heap-allocated array, will result in a compilation error on some compilers, or otherwise produce incorrect results.
這大致上相當於:
sizeof(array) / sizeof((array)[0])
-
Py_MEMBER_SIZE(type, member)¶
以位元組為單位回傳結構 (type) member 的大小。
Corresponds roughly to
sizeof(((type *)NULL)->member).在 3.6 版被加入.
Macro definition utilities¶
-
Py_FORCE_EXPANSION(X)¶
This is equivalent to
X, which is useful for token-pasting in macros, as macro expansions in X are forcefully evaluated by the preprocessor.
-
Py_STRINGIFY(x)¶
將
x轉換為 C 字串。例如Py_STRINGIFY(123)會回傳"123"。在 3.4 版被加入.
Declaration utilities¶
The following macros can be used in declarations. They are most useful for defining the C API itself, and have limited use for extension authors. Most of them expand to compiler-specific spellings of common extensions to the C language.
-
Py_ALWAYS_INLINE¶
要求編譯器總是嵌入靜態行內函式 (static inline function),編譯器可以忽略它並決定不嵌入該函式。
Corresponds to
always_inlineattribute in GCC and__forceinlinein MSVC.在禁用函式嵌入的除錯模式下建置 Python 時,它可用於嵌入有性能要求的靜態行內函式。例如,MSC 在除錯模式下建置時禁用函式嵌入。
盲目地使用 Py_ALWAYS_INLINE 標記靜態行內函式可能會導致更差的性能(例如程式碼大小增加)。在成本/收益分析方面,編譯器通常比開發人員更聰明。
如果 Python 是在除錯模式下建置(如果
Py_DEBUG巨集有被定義),Py_ALWAYS_INLINE巨集就什麼都不會做。它必須在函式回傳型別之前被指定。用法:
static inline Py_ALWAYS_INLINE int random(void) { return 4; }
在 3.11 版被加入.
-
Py_NO_INLINE¶
禁用函式的嵌入。例如,它減少了 C 堆疊的消耗:對大量嵌入程式碼的 LTO+PGO 建置很有用(請參閱 bpo-33720)。
Corresponds to the
noinlineattribute/specification on GCC and MSVC.用法:
Py_NO_INLINE static int random(void) { return 4; }
在 3.11 版被加入.
-
Py_DEPRECATED(version)¶
Use this to declare APIs that were deprecated in a specific CPython version. The macro must be placed before the symbol name.
範例:
Py_DEPRECATED(3.8) PyAPI_FUNC(int) Py_OldFunction(void);
在 3.8 版的變更: 新增了 MSVC 支援。
-
Py_LOCAL(type)¶
Declare a function returning the specified type using a fast-calling qualifier for functions that are local to the current file. Semantically, this is equivalent to
static type.
-
Py_LOCAL_SYMBOL¶
Macro used to declare a symbol as local to the shared library (hidden). On supported platforms, it ensures the symbol is not exported.
On compatible versions of GCC/Clang, it expands to
__attribute__((visibility("hidden"))).
-
Py_EXPORTED_SYMBOL¶
Macro used to declare a symbol (function or data) as exported. On Windows, this expands to
__declspec(dllexport). On compatible versions of GCC/Clang, it expands to__attribute__((visibility("default"))). This macro is for defining the C API itself; extension modules should not use it.
-
Py_IMPORTED_SYMBOL¶
Macro used to declare a symbol as imported. On Windows, this expands to
__declspec(dllimport). This macro is for defining the C API itself; extension modules should not use it.
-
PyAPI_FUNC(type)¶
Macro used by CPython to declare a function as part of the C API. Its expansion depends on the platform and build configuration. This macro is intended for defining CPython's C API itself; extension modules should not use it for their own symbols.
-
PyAPI_DATA(type)¶
Macro used by CPython to declare a public global variable as part of the C API. Its expansion depends on the platform and build configuration. This macro is intended for defining CPython's C API itself; extension modules should not use it for their own symbols.
Outdated macros¶
The following macros have been used to features that have been standardized in C11.
-
Py_ALIGNED(num)¶
Specify alignment to num bytes on compilers that support it.
Consider using the C11 standard
_Alignasspecifier over this macro.
-
Py_LL(number)¶
-
Py_ULL(number)¶
Use number as a
long longorunsigned long longinteger literal, respectively.Expands to number followed by
LLorLLU, respectively, but will expand to some compiler-specific suffixes on some older compilers.Consider using the C99 standard suffixes
LLandLLUdirectly.
物件、型別和參照計數¶
大多數 Python/C API 函式都有一個或多個引數以及一個型別為 PyObject* 的回傳值,此型別是一個指標,指向一個表示任意 Python 物件的晦暗 (opaque) 資料型別。由於在大多數情況下,Python 語言以相同的方式處理所有 Python 物件型別(例如賦值、作用域規則和引數傳遞),因此它們應該由單個 C 型別來表示。幾乎所有的 Python 物件都存在於堆積 (heap) 中:你永遠不會聲明 PyObject 型別的自動變數或靜態變數,只能聲明 PyObject* 型別的指標變數。唯一的例外是型別物件;由於它們絕不能被釋放,因此它們通常是靜態 PyTypeObject 物件。
所有 Python 物件(甚至是 Python 整數)都有一個型別 (type) 和一個參照計數 (reference count)。一個物件的型別決定了它是什麼種類的物件(例如一個整數、一個 list 或一個使用者定義的函式;還有更多型別,請見標準型別階層)。對於每個眾所周知的型別,都有一個巨集來檢查物件是否屬於該型別;例如,若(且唯若)*a* 指向的物件是 Python list 時,PyList_Check(a) 為真。
參照計數¶
參照計數很重要,因為現今的電腦記憶體大小是有限的(而且通常是非常有限的);它計算有多少個不同的地方用有了一個物件的強參照。這樣的地方可以是另一個物件,或者全域(或靜態)C 變數,或者某個 C 函式中的本地變數。當一個物件的最後一個強參照被釋放時(即其的參照計數變為零),該物件將被解除配置 (deallocated)。如果它包含對其他物件的參照,則它們的參照會被釋放。如果這樣的釋放使得再也沒有任何對於它們的參照,則可以依次為那些其他物件解除配置,依此類推。(此處相互參照物件的存在是個明顯的問題;目前,解決方案是「就不要那樣做」。)
參照計數總是被明確地操作。正常的方法是使用巨集 Py_INCREF() 來取得對於物件的參照(即參照計數加一),並使用巨集 Py_DECREF() 來釋放參照(即將參照計數減一)。Py_DECREF() 巨集比 incref 巨集複雜得多,因為它必須檢查參照計數是否變為零,然後呼叫物件的釋放器 (deallocator)。釋放器是包含在物件型別結構中的函式指標。特定型別的釋放器,在如果是一個複合物件型別(例如 list)時負責釋放物件中包含的其他物件的參照,並執行任何需要的額外完結步驟。參照計數不可能溢出;至少與虛擬記憶體中用來保存參照計數的不同記憶體位置數量一樣多的位元會被使用(假設 sizeof(Py_ssize_t) >= sizeof(void*))。因此參照計數增加是一個簡單的操作。
沒有必要為每個包含物件指標的本地變數物件都持有一個強參照(即增加參照計數)。理論上,當變數指向它時,物件的參照計數會增加 1,而當變數離開作用域時就會減少 1。然而這兩者會相互抵消,所以最後參照計數沒有改變。使用參照計數的唯一真正原因是防止物件還有變數指向它時被解除配置。如果我們知道至少有一個物件的其他參照生存了至少與我們的變數一樣久,就不需要臨時增加建立新的強參照(即增加參照計數)。出現這種情況的一個重要情況是在從 Python 呼叫的擴充模組中作為引數傳遞給 C 函式的物件;呼叫機制保證在呼叫期間保持對每個參數的參照。
然而,一個常見的陷阱是從一個 list 中提取一個物件並保留它一段時間而不取得其參照。某些其他操作可能會從列表中刪除該物件,減少其參照計數並可能取消分配它。真正的危險是看似無害的操作可能會叫用可以執行此操作的任意 Python 程式碼;有一個程式碼路徑允許控制權從 Py_DECREF() 回歸使用者,因此幾乎任何操作都有潛在危險。
一種安全的方法是都使用通用 (generics) 操作(名稱以 PyObject_、PyNumber_、PySequence_ 或 PyMapping_ 開頭的函式)。這些操作總是建立新的對於它們回傳物件的強參照(即增加其參照計數)。這讓呼叫者有責任在處理完結果後呼叫 Py_DECREF();這就成為第二本質。
參照計數詳細資訊¶
Python/C API 中函式的參照計數行為最好用參照的所有權來解釋。所有權附屬於參照而非物件(物件並非被擁有,它們總是共享的)。「擁有參照」意味著當不再需要該參照時,負責在其上呼叫 Py_DECREF。所有權也可以轉移,這意味著接收參照所有權的程式碼最終會負責在不需要參照時透過呼叫 Py_DECREF() 或 Py_XDECREF() 釋放參照 --- 或者將這個責任再傳遞出去(通常是給它的呼叫者)。當一個函式將參照的所有權傳遞給它的呼叫者時,呼叫者被稱為接收到一個新參照。當沒有所有權轉移時,呼叫者被稱為借用參照。如果是借用參照就不需要做任何事情。
相反地,當呼叫的函式傳入物件的參照時,有兩種可能性:函式有竊取 (steal) 物件的參照,或者沒有。 竊取參照意味著當你將參照傳遞給函式時,該函式假定它現在擁有該參照,並且你不再對它負責。
很少有函式會竊取參照;兩個值得注意的例外是 PyList_SetItem() 和 PyTuple_SetItem(),它們竊取了對項目的參照(但不是對項目所在的 tuple 或 list 的參照!)。因為有著使用新建立的物件來增加 (populate) tuple 或 list 的習慣,這些函式旨在竊取參照;例如,建立 tuple (1, 2, "three") 的程式碼可以如下所示(先暫時忘記錯誤處理;更好的編寫方式如下所示):
PyObject *t;
t = PyTuple_New(3);
PyTuple_SetItem(t, 0, PyLong_FromLong(1L));
PyTuple_SetItem(t, 1, PyLong_FromLong(2L));
PyTuple_SetItem(t, 2, PyUnicode_FromString("three"));
這裡 PyLong_FromLong() 會回傳一個新的參照,它立即被 PyTuple_SetItem() 竊取。如果你想繼續使用一個物件,儘管對它的參照將被竊取,請在呼叫參照竊取函式之前使用 Py_INCREF() 來取得另一個參照。
附帶地說,PyTuple_SetItem() 是設定 tuple 項目的唯一方法; PySequence_SetItem() 和 PyObject_SetItem() 拒絕這樣做,因為 tuple 是一種不可變 (immutable) 的資料型別。你應該只對你自己建立的 tuple 使用 PyTuple_SetItem()。
可以使用 PyList_New() 和 PyList_SetItem() 編寫用於填充列表的等效程式碼。
但是在實際操作中你很少會使用這些方法來建立和增加 tuple 和 list。有一個通用函式 Py_BuildValue() 可以從 C 值建立最常見的物件,由 format string 引導。例如上面的兩個程式碼可以用以下程式碼替換(它還負責了錯誤檢查):
PyObject *tuple, *list;
tuple = Py_BuildValue("(iis)", 1, 2, "three");
list = Py_BuildValue("[iis]", 1, 2, "three");
更常見的是以那些借用參照的項目來使用 PyObject_SetItem() 及其系列函式,比如傳遞給你正在編寫的函式的引數。在那種情況下,他們關於參照的行為會比較穩健,因為你不取得新的一個參照就可以放棄參照(「讓它被竊取」)。例如,此函式將 list(實際上是任何可變序列)的所有項目設定於給定項目:
int
set_all(PyObject *target, PyObject *item)
{
Py_ssize_t i, n;
n = PyObject_Length(target);