# 在 Cython 中使用 C ++
> 原文: [http://docs.cython.org/en/latest/src/userguide/wrapping_CPlusPlus.html](http://docs.cython.org/en/latest/src/userguide/wrapping_CPlusPlus.html)
## 概述
Cython 對大多數 C ++語言都有本機支持。特別:
* 可以使用`new`和`del`關鍵字動態分配 C ++對象。
* C ++對象可以進行堆棧分配。
* 可以使用 new 關鍵字`cppclass`聲明 C ++類。
* 支持模板化的類和函數。
* 支持重載功能。
* 支持重載 C ++運算符(例如 operator +,operator [],...)。
### 程序概述
包裝 C ++文件的一般過程現在可以描述如下:
* 在`setup.py`腳本中指定 C ++語言,或在源文件中指定本地。
* 使用`cdef extern from`塊和(如果存在)C ++命名空間名稱創建一個或多個`.pxd`文件。在這些塊中:
* 將類聲明為`cdef cppclass`塊
* 聲明公共名稱(變量,方法和構造函數)
* `cimport`它們位于一個或多個擴展模塊(`.pyx`文件)中。
## 一個簡單的教程
### 示例 C ++ API
這是一個很小的 C ++ API,我們將在本文檔中將其作為示例。我們假設它將位于名為`Rectangle.h`的頭文件中:
```py
#ifndef RECTANGLE_H
#define RECTANGLE_H
namespace shapes {
class Rectangle {
public:
int x0, y0, x1, y1;
Rectangle();
Rectangle(int x0, int y0, int x1, int y1);
~Rectangle();
int getArea();
void getSize(int* width, int* height);
void move(int dx, int dy);
};
}
#endif
```
以及名為`Rectangle.cpp`的文件中的實現:
```py
#include <iostream>
#include "Rectangle.h"
namespace shapes {
// Default constructor
Rectangle::Rectangle () {}
// Overloaded constructor
Rectangle::Rectangle (int x0, int y0, int x1, int y1) {
this->x0 = x0;
this->y0 = y0;
this->x1 = x1;
this->y1 = y1;
}
// Destructor
Rectangle::~Rectangle () {}
// Return the area of the rectangle
int Rectangle::getArea () {
return (this->x1 - this->x0) * (this->y1 - this->y0);
}
// Get the size of the rectangle.
// Put the size in the pointer args
void Rectangle::getSize (int *width, int *height) {
(*width) = x1 - x0;
(*height) = y1 - y0;
}
// Move the rectangle by dx dy
void Rectangle::move (int dx, int dy) {
this->x0 += dx;
this->y0 += dy;
this->x1 += dx;
this->y1 += dy;
}
}
```
這非常愚蠢,但應該足以證明所涉及的步驟。
### 聲明 C ++類接口
包裝 C ++類的過程與包裝普通 C 結構的過程非常類似,只需添加幾個。讓我們從創建基本`cdef extern from`塊開始:
```py
cdef extern from "Rectangle.h" namespace "shapes":
```
這將使得 Rectangle 的 C ++類 def 可用。請注意名稱空間聲明。命名空間僅用于創建對象的完全限定名稱,并且可以嵌套(例如`"outer::inner"`)或甚至引用類(例如`"namespace::MyClass`在 MyClass 上聲明靜態成員)。
#### 使用 cdef cppclass 聲明類
現在,讓我們從塊中將 Rectangle 類添加到此 extern - 只需從 Rectangle.h 復制類名并調整 Cython 語法,現在它變為:
```py
cdef extern from "Rectangle.h" namespace "shapes":
cdef cppclass Rectangle:
```
#### 添加公共屬性
我們現在需要聲明在 Cython 上使用的屬性和方法。我們將這些聲明放在一個名為`Rectangle.pxd`的文件中。您可以將其視為可由 Cython 讀取的頭文件:
```py
cdef extern from "Rectangle.cpp":
pass
# Declare the class with cdef
cdef extern from "Rectangle.h" namespace "shapes":
cdef cppclass Rectangle:
Rectangle() except +
Rectangle(int, int, int, int) except +
int x0, y0, x1, y1
int getArea()
void getSize(int* width, int* height)
void move(int, int)
```
請注意,構造函數聲明為“except +”。如果 C ++代碼或初始內存分配由于失敗而引發異常,這將使 Cython 安全地引發適當的 Python 異常(見下文)。如果沒有此聲明,Cython 將不會處理源自構造函數的 C ++異常。
我們使用這些線:
```py
cdef extern from "Rectangle.cpp":
pass
```
包含來自`Rectangle.cpp`的 C ++代碼。也可以指定`Rectangle.cpp`為源的 distutils。為此,您可以在`.pyx`(不是`.pxd`)文件的頂部添加此指令:
```py
# distutils: sources = Rectangle.cpp
```
請注意,使用`cdef extern from`時,指定的路徑相對于當前文件,但如果使用 distutils 指令,則路徑相對于`setup.py`。如果要在運行`setup.py`時發現源的路徑,可以使用`cythonize()`功能的`aliases`參數。
#### 用包裝的 C ++類聲明一個 var
我們將創建一個名為`rect.pyx`的`.pyx`文件來構建我們的包裝器。我們使用的是`Rectangle`以外的名稱,但如果您希望為包裝器提供與 C ++類相同的名稱,請參閱 [解決命名沖突](external_C_code.html#resolve-conflicts) 的部分。
在其中,我們使用 cdef 使用 C ++ `new`語句聲明類的 var:
```py
# distutils: language = c++
from Rectangle cimport Rectangle
def main():
rec_ptr = new Rectangle(1, 2, 3, 4) # Instantiate a Rectangle object on the heap
try:
rec_area = rec_ptr.getArea()
finally:
del rec_ptr # delete heap allocated object
cdef Rectangle rec_stack # Instantiate a Rectangle object on the stack
```
這條線:
```py
# distutils: language = c++
```
是向 Cython 表明這個`.pyx`文件必須編譯為 C ++。
只要它具有“默認”構造函數,也可以聲明堆棧分配的對象:
```py
cdef extern from "Foo.h":
cdef cppclass Foo:
Foo()
def func():
cdef Foo foo
...
```
請注意,與 C ++一樣,如果類只有一個構造函數并且它是一個無效的,那么就沒有必要聲明它。
### 創建 Cython 包裝類
此時,我們已經將我們的 pyx 文件的命名空間暴露給 C ++ Rectangle 類型的接口。現在,我們需要從外部 Python 代碼訪問它(這是我們的全部觀點)。
常見的編程實踐是創建一個 Cython 擴展類型,它將 C ++實例作為屬性保存并創建一堆轉發方法。所以我們可以將 Python 擴展類型實現為:
```py
# distutils: language = c++
from Rectangle cimport Rectangle
# Create a Cython extension type which holds a C++ instance
# as an attribute and create a bunch of forwarding methods
# Python extension type.
cdef class PyRectangle:
cdef Rectangle c_rect # Hold a C++ instance which we're wrapping
def __cinit__(self, int x0, int y0, int x1, int y1):
self.c_rect = Rectangle(x0, y0, x1, y1)
def get_area(self):
return self.c_rect.getArea()
def get_size(self):
cdef int width, height
self.c_rect.getSize(&width, &height)
return width, height
def move(self, dx, dy):
self.c_rect.move(dx, dy)
```
我們終于得到它了。從 Python 的角度來看,這種擴展類型的外觀和感覺就像本機定義的 Rectangle 類一樣。需要注意的是,如果要提供屬性訪問權限,可以實現一些屬性:
```py
# distutils: language = c++
from Rectangle cimport Rectangle
cdef class PyRectangle:
cdef Rectangle c_rect
def __cinit__(self, int x0, int y0, int x1, int y1):
self.c_rect = Rectangle(x0, y0, x1, y1)
def get_area(self):
return self.c_rect.getArea()
def get_size(self):
cdef int width, height
self.c_rect.getSize(&width, &height)
return width, height
def move(self, dx, dy):
self.c_rect.move(dx, dy)
# Attribute access
@property
def x0(self):
return self.c_rect.x0
@x0.setter
def x0(self, x0):
self.c_rect.x0 = x0
# Attribute access
@property
def x1(self):
return self.c_rect.x1
@x1.setter
def x1(self, x1):
self.c_rect.x1 = x1
# Attribute access
@property
def y0(self):
return self.c_rect.y0
@y0.setter
def y0(self, y0):
self.c_rect.y0 = y0
# Attribute access
@property
def y1(self):
return self.c_rect.y1
@y1.setter
def y1(self, y1):
self.c_rect.y1 = y1
```
Cython 使用 nullary 構造函數初始化 cdef 類的 C ++類屬性。如果要包裝的類沒有構造函數,則必須存儲指向包裝類的指針并手動分配和取消分配它。一個方便和安全的地方是 <cite>__cinit__</cite> 和 <cite>__dealloc__</cite> 方法,保證在創建和刪除 Python 實例時只調用一次。
```py
# distutils: language = c++
from Rectangle cimport Rectangle
cdef class PyRectangle:
cdef Rectangle*c_rect # hold a pointer to the C++ instance which we're wrapping
def __cinit__(self, int x0, int y0, int x1, int y1):
self.c_rect = new Rectangle(x0, y0, x1, y1)
def __dealloc__(self):
del self.c_rect
```
## 編譯和導入
要編譯 Cython 模塊,必須有一個`setup.py`文件:
```py
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules=cythonize("rect.pyx"))
```
運行`$ python setup.py build_ext --inplace`
要測試它,打開 Python 解釋器:
```py
>>> import rect
>>> x0, y0, x1, y1 = 1, 2, 3, 4
>>> rect_obj = rect.PyRectangle(x0, y0, x1, y1)
>>> print(dir(rect_obj))
['__class__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__',
'__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__',
'__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__',
'__setstate__', '__sizeof__', '__str__', '__subclasshook__', 'get_area', 'get_size', 'move']
```
## 高級 C ++特性
我們在這里描述了上面教程中沒有討論過的所有 C ++特性。
### 重載
重載非常簡單。只需使用不同的參數聲明方法并使用其中任何一個:
```py
cdef extern from "Foo.h":
cdef cppclass Foo:
Foo(int)
Foo(bool)
Foo(int, bool)
Foo(int, int)
```
### 重載運算符
Cython 使用 C ++命名來重載運算符:
```py
cdef extern from "foo.h":
cdef cppclass Foo:
Foo()
Foo operator+(Foo)
Foo operator-(Foo)
int operator*(Foo)
int operator/(int)
int operator*(int, Foo) # allows 1*Foo()
# nonmember operators can also be specified outside the class
double operator/(double, Foo)
cdef Foo foo = new Foo()
foo2 = foo + foo
foo2 = foo - foo
x = foo * foo2
x = foo / 1
x = foo[0] * foo2
x = foo[0] / 1
x = 1*foo[0]
cdef double y
y = 2.0/foo[0]
```
請注意,如果有一個 _ 指針 _ 到 C ++對象,則必須進行解除引用以避免執行指針算術而不是對對象本身進行算術運算:
```py
cdef Foo* foo_ptr = new Foo()
foo = foo_ptr[0] + foo_ptr[0]
x = foo_ptr[0] / 2
del foo_ptr
```
### 嵌套類聲明
C ++允許嵌套類聲明。類聲明也可以嵌套在 Cython 中:
```py
# distutils: language = c++
cdef extern from "<vector>" namespace "std":
cdef cppclass vector[T]:
cppclass iterator:
T operator*()
iterator operator++()
bint operator==(iterator)
bint operator!=(iterator)
vector()
void push_back(T&)
T& operator[](int)
T& at(int)
iterator begin()
iterator end()
cdef vector[int].iterator iter #iter is declared as being of type vector<int>::iterator
```
請注意,嵌套類使用`cppclass`聲明但沒有`cdef`,因為它已經是`cdef`聲明部分的一部分。
### C ++運算符與 Python 語法不兼容
Cython 嘗試使其語法盡可能接近標準 Python。因此,某些 C ++運算符(如 preincrement `++foo`或解除引用運算符`*foo`)不能與 C ++使用相同的語法。 Cython 提供了在特殊模塊`cython.operator`中替換這些運算符的函數。提供的功能是:
* 用于解除引用的`cython.operator.dereference`。 `dereference(foo)`將生成 C ++代碼`*(foo)`
* `cython.operator.preincrement`用于預增量。 `preincrement(foo)`將生成 C ++代碼`++(foo)`。類似地`predecrement`,`postincrement`和`postdecrement`。
* 逗號運算符的`cython.operator.comma`。 `comma(a, b)`將生成 C ++代碼`((a), (b))`。
這些功能需要被引導。當然,可以使用`from ... cimport ... as`來獲得更短且更易讀的功能。例如:`from cython.operator cimport dereference as deref`。
為了完整起見,還值得一提的是`cython.operator.address`,它也可以寫成`&foo`。
### 模板
Cython 使用括號語法進行模板化。包裝 C ++向量的一個簡單示例:
```py
# distutils: language = c++
# import dereference and increment operators
from cython.operator cimport dereference as deref, preincrement as inc
cdef extern from "<vector>" namespace "std":
cdef cppclass vector[T]:
cppclass iterator:
T operator*()
iterator operator++()
bint operator==(iterator)
bint operator!=(iterator)
vector()
void push_back(T&)
T& operator[](int)
T& at(int)
iterator begin()
iterator end()
cdef vector[int] *v = new vector[int]()
cdef int i
for i in range(10):
v.push_back(i)
cdef vector[int].iterator it = v.begin()
while it != v.end():
print(deref(it))
inc(it)
del v
```
可以將多個模板參數定義為列表,例如`[T, U, V]`或`[int, bool, char]`。可以通過寫`[T, U, V=*]`來指示可選的模板參數。如果 Cython 需要顯式引用不完整模板實例化的默認模板參數的類型,它將寫入`MyClass<T, U>::V`,因此如果類為其模板參數提供 typedef,則最好在此處使用該名稱。
模板函數的定義與類模板類似,模板參數列表位于函數名稱后面:
```py
# distutils: language = c++
cdef extern from "<algorithm>" namespace "std":
T max[T](T a, T b)
print(max[long](3, 4))
print(max(1.5, 2.5)) # simple template argument deduction
```
### 標準庫
C ++標準庫的大多數容器已在位于 [/ Cython / Includes / libcpp](https://github.com/cython/cython/tree/master/Cython/Includes/libcpp) 中的 pxd 文件中聲明。這些容器是:deque,list,map,pair,queue,set,stack,vector。
例如:
```py
# distutils: language = c++
from libcpp.vector cimport vector
cdef vector[int] vect
cdef int i, x
for i in range(10):
vect.push_back(i)
for i in range(10):
print(vect[i])
for x in vect:
print(x)
```
[/ Cython / Includes / libcpp](https://github.com/cython/cython/tree/master/Cython/Includes/libcpp) 中的 pxd 文件也是如何聲明 C ++類的好例子。
STL 容器強制執行相應的 Python 內置類型。轉換是通過賦值給類型變量(包括類型化函數參數)或通過顯式強制轉換來觸發的,例如:
```py
# distutils: language = c++
from libcpp.string cimport string
from libcpp.vector cimport vector
py_bytes_object = b'The knights who say ni'
py_unicode_object = u'Those who hear them seldom live to tell the tale.'
cdef string s = py_bytes_object
print(s) # b'The knights who say ni'
cdef string cpp_string = <string> py_unicode_object.encode('utf-8')
print(cpp_string) # b'Those who hear them seldom live to tell the tale.'
cdef vector[int] vect = range(1, 10, 2)
print(vect) # [1, 3, 5, 7, 9]
cdef vector[string] cpp_strings = b'It is a good shrubbery'.split()
print(cpp_strings[1]) # b'is'
```
可以使用以下強制措施:
<colgroup><col width="35%"> <col width="31%"> <col width="33%"></colgroup>
| Python type =&gt; | _C ++類型 _ | =&GT; Python 類型 |
| --- | --- | --- |
| 字節 | 的 std :: string | bytes |
| 迭代 | 的 std ::矢量 | 名單 |
| iterable | 的 std ::名單 | list |
| iterable | 的 std ::設為 | 組 |
| 可迭代的(len 2) | 的 std ::對 | 元組(len 2) |
所有轉換都會創建一個新容器并將數據復制到其中。容器中的物品自動轉換成相應的類型,包括遞歸地轉換容器內的容器,例如容器。字符串映射的 C ++向量。
通過`for .. in`語法(包括列表推導)支持對 stl 容器(或實際上任何具有`begin()`和`end()`方法的類返回支持遞增,解除引用和比較的對象的迭代)的迭代。例如,人們可以寫:
```py
# distutils: language = c++
from libcpp.vector cimport vector
def main():
cdef vector[int] v = [4, 6, 5, 10, 3]
cdef int value
for value in v:
print(value)
return [x*x for x in v if x % 2 == 0]
```
如果未指定循環目標變量,則 [類型推斷](source_files_and_compilation.html#compiler-directives) 使用類型`*container.begin()`的賦值。
注意
支持切片 stl 容器,你可以做`for x in my_vector[:5]: ...`,但與指針切片不同,它將創建一個臨時的 Python 對象并迭代它。因此使迭代非常緩慢。出于性能原因,您可能希望避免切片 C ++容器。
### 使用默認構造函數簡化包裝
如果您的擴展類型使用默認構造函數(不傳遞任何參數)實例化包裝的 C ++類,您可以通過將生命周期處理直接綁定到 Python 包裝器對象的生命周期來簡化生命周期處理。您可以聲明一個實例,而不是指針屬性:
```py
# distutils: language = c++
from libcpp.vector cimport vector
cdef class VectorStack:
cdef vector[int] v
def push(self, x):
self.v.push_back(x)
def pop(self):
if self.v.empty():
raise IndexError()
x = self.v.back()
self.v.pop_back()
return x
```
Cython 將自動生成在創建 Python 對象時實例化 C ++對象實例的代碼,并在 Python 對象被垃圾回收時刪除它。
### 例外情況
Cython 不能拋出 C ++異常,或者用 try-except 語句捕獲它們,但是可以將函數聲明為可能引發 C ++異常并將其轉換為 Python 異常。例如,
```py
cdef extern from "some_file.h":
cdef int foo() except +
```
這會將 try 和 C ++錯誤轉換為適當的 Python 異常。根據下表執行轉換(從 C ++標識符中省略`std::`前綴):
<colgroup><col width="52%"> <col width="48%"></colgroup>
| C ++ | 蟒蛇 |
| --- | --- |
| `bad_alloc` | `MemoryError` |
| `bad_cast` | `TypeError` |
| `bad_typeid` | `TypeError` |
| `domain_error` | `ValueError` |
| `invalid_argument` | `ValueError` |
| `ios_base::failure` | `IOError` |
| `out_of_range` | `IndexError` |
| `overflow_error` | `OverflowError` |
| `range_error` | `ArithmeticError` |
| `underflow_error` | `ArithmeticError` |
| (所有其他人) | `RuntimeError` |
保留`what()`消息(如果有)。請注意,C ++ `ios_base_failure`可以表示 EOF,但是沒有足夠的信息供 Cython 識別,因此請注意 IO 流上的異常掩碼。
```py
cdef int bar() except +MemoryError
```
這將捕獲任何 C ++錯誤并在其位置引發 Python MemoryError。 (任何 Python 異常在這里都有效。)
```py
cdef int raise_py_error()
cdef int something_dangerous() except +raise_py_error
```
如果 something_dangerous 引發了 C ++異常,那么將調用 raise_py_error,這允許自定義 C ++到 Python 錯誤“翻譯”。如果 raise_py_error 實際上沒有引發異常,則會引發 RuntimeError。
還有一種特殊的形式:
```py
cdef int raise_py_or_cpp() except +*
```
對于那些可能引發 Python 或 C ++異常的函數。
### 靜態成員方法
如果 Rectangle 類具有靜態成員:
```py
namespace shapes {
class Rectangle {
...
public:
static void do_something();
};
}
```
你可以使用 Python @staticmethod 裝飾器聲明它,即:
```py
cdef extern from "Rectangle.h" namespace "shapes":
cdef cppclass Rectangle:
...
@staticmethod
void do_something()
```
### 聲明/使用參考文獻
Cython 支持使用標準`Type&`語法聲明左值引用。但請注意,沒有必要將 extern 函數的參數聲明為引用(const 或其他),因為它對調用者的語法沒有影響。
### `auto`關鍵字
雖然 Cython 沒有`auto`關鍵字,但是沒有用`cdef`顯式輸入的 Cython 局部變量是從 _ 右側的類型中推斷出所有 _ 的分配(參見`infer_types` [編譯指令](source_files_and_compilation.html#compiler-directives) )。在處理返回復雜,嵌套,模板化類型的函數時,這尤其方便,例如:
```py
cdef vector[int] v = ...
it = v.begin()
```
(當然,對于支持迭代協議的對象,`for .. in`語法是首選。)
## RTTI 和 typeid()
Cython 支持`typeid(...)`運算符。
> 來自 cython.operator cimport typeid
`typeid(...)`運算符返回`const type_info &`類型的對象。
如果要將 type_info 值存儲在 C 變量中,則需要將其存儲為指針而不是引用:
```py
from libcpp.typeinfo cimport type_info
cdef const type_info* info = &typeid(MyClass)
```
如果將無效類型傳遞給`typeid`,它將拋出`std::bad_typeid`異常,該異常在 Python 中轉換為`TypeError`異常。
`libcpp.typeindex`中提供了另一個與 C ++ 11 兼容的 RTTI 相關類`std::type_index`。
## 在 setup.py 中指定 C ++語言
可以在`setup.py`文件中聲明它們,而不是在源文件中指定語言和源:
```py
from distutils.core import setup
from Cython.Build import cythonize
setup(ext_modules = cythonize(
"rect.pyx", # our Cython source
sources=["Rectangle.cpp"], # additional source file(s)
language="c++", # generate C++ code
))
```
Cython 將生成并編譯`rect.cpp`文件(來自`rect.pyx`),然后它將編譯`Rectangle.cpp`(`Rectangle`類的實現)并將兩個目標文件一起鏈接到 Linux 上的`rect.so`或`rect.pyd`在 Windows 上,然后可以使用`import rect`在 Python 中導入(如果忘記鏈接`Rectangle.o`,則在 Python 中導入庫時將丟失符號)。
請注意,`language`選項對傳遞給`cythonize()`的用戶提供的 Extension 對象沒有影響。它僅用于按文件名找到的模塊(如上例所示)。
Cython 版本中最大 0.21 的`cythonize()`功能無法識別`language`選項,需要將其指定為描述擴展名的`Extension`選項,然后由`cythonize()`處理,如下所示:
```py
from distutils.core import setup, Extension
from Cython.Build import cythonize
setup(ext_modules = cythonize(Extension(
"rect", # the extension name
sources=["rect.pyx", "Rectangle.cpp"], # the Cython source and
# additional C++ source files
language="c++", # generate and compile C++ code
)))
```
選項也可以直接從源文件傳遞,這通常是可取的(并覆蓋任何全局選項)。從版本 0.17 開始,Cython 還允許以這種方式將外部源文件傳遞到`cythonize()`命令。這是一個簡化的 setup.py 文件:
```py
from distutils.core import setup
from Cython.Build import cythonize
setup(
name = "rectangleapp",
ext_modules = cythonize('*.pyx'),
)
```
在.pyx 源文件中,將其寫入第一個注釋塊,在任何源代碼之前,以 C ++模式編譯它并將其靜態鏈接到`Rectangle.cpp`代碼文件:
```py
# distutils: language = c++
# distutils: sources = Rectangle.cpp
```
Note
使用 distutils 指令時,路徑相對于 distutils 運行的工作目錄(通常是`setup.py`所在的項目根目錄)。
要手動編譯(例如使用`make`),可以使用`cython`命令行實用程序生成 C ++ `.cpp`文件,然后將其編譯為 python 擴展。使用`--cplus`選項打開`cython`命令的 C ++模式。
## 警告和限制
### 訪問僅限 C 的函數
每當生成 C ++代碼時,Cython 都會生成函數的聲明和調用,假設這些函數是 C ++(即,未聲明為`extern "C" {...}`。如果 C 函數具有 C ++入口點,這是可以的,但如果它們只是 C,那么你將遇到障礙。如果你有一個 C ++ Cython 模塊需要調用 pure-C 函數,你需要編寫一個小的 C ++ shim 模塊:
* 包括 extern“C”塊中所需的 C 頭
* 包含 C ++中的最小轉發函數,每個函數都調用相應的 pure-C 函數
### C ++左值
C ++允許返回引用的函數為 left-values。 Cython 目前不支持此功能。 `cython.operator.dereference(foo)`也不被視為左值。
- 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 后端