cppyy 基本类型#
C++ 的内置类型比 Python 丰富得多。大多数 Python 代码对此可以相对保持不可知,cppyy
在适当的时候提供自动转换。另一方面,Python 的内置类型(如列表和映射)比 C++ 中的任何内置类型都要丰富得多。这些类型被映射到它们的标准模板库等价物。
下面的示例中使用的 C++ 代码可以在这里找到,并且假设在运行任何示例代码片段之前已经加载了该代码。下载它,将其保存为名为 features.h
的文件,然后简单地包含它:
import cppyy
cppyy.include('features.h')
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[1], line 1
----> 1 import cppyy
2 cppyy.include('features.h')
ModuleNotFoundError: No module named 'cppyy'
cppyy 内置类型#
Python 和 C++ 之间的内置数据类型的选择差异很大。在可能的情况下,内置数据类型映射到预期的等效 Python 类型,但要注意可能存在的大小差异、不同的精度或舍入等。例如,C++ 的 float
返回为 Python 的 float
,实际上是 C++ 的 double
。如果大小允许,转换是自动的。例如,C++ 的 unsigned int
变成 Python2 的 long
或 Python3 的 int
,但无符号性仍然保留:
cppyy.gbl.gUint
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[2], line 1
----> 1 cppyy.gbl.gUint
NameError: name 'cppyy' is not defined
type(cppyy.gbl.gUint)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[3], line 1
----> 1 type(cppyy.gbl.gUint)
NameError: name 'cppyy' is not defined
cppyy.gbl.gUint = -1
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[4], line 1
----> 1 cppyy.gbl.gUint = -1
NameError: name 'cppyy' is not defined
在某些平台上,8 位整数类型(如 int8_t
和 uint8_t
)表示为 char
类型。为了保持一致性,这些类型映射到 Python int
。
有些类型在 Python 中是内置的,但在 C++ 中是(STL)类。例如,str
与 std::string
(另见字符串部分)以及 complex
与 std::complex
。这些类已经被 python 化,以尽可能表现得相同。例如,字符串比较可以直接工作,而 std::complex
具有 real
和 imag
属性:
c = cppyy.gbl.std.complex['double'](1, 2)
c
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[5], line 1
----> 1 c = cppyy.gbl.std.complex['double'](1, 2)
2 c
NameError: name 'cppyy' is not defined
c.real, c.imag
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[6], line 1
----> 1 c.real, c.imag
NameError: name 'c' is not defined
s = cppyy.gbl.std.string("aap")
type(s)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[7], line 1
----> 1 s = cppyy.gbl.std.string("aap")
2 type(s)
NameError: name 'cppyy' is not defined
s == "aap"
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[8], line 1
----> 1 s == "aap"
NameError: name 's' is not defined
要通过 C++ 的 char
(有符号或无符号)传递参数,使用大小为 1
的 Python 字符串。在许多情况下,也可以使用 ctypes
模块中的显式 C 类型,但该模块没有公共 API(用于类型转换或其他用途),所以支持有些有限。
在可能的情况下,C++ 的 std::vector
和 Python 的 list
及 tuple
之间存在自动转换,因为它们通常以类似的方式使用。然而,这些数据类型具有完全不同的内存布局,而 std::vector
要求所有元素都是相同的类型并在内存中连续排列。因此,转换需要类型检查、内存分配和复制。这可能会相当昂贵。
tuple
tuple
cppyy 数组#
通过 array
中的数组(或任何其他实现 Python 缓冲接口的内置类型数组,如 numpy
数组)以及 cppyy
中用于返回和变量访问的低级视图类型来支持内置数组(同样实现了缓冲接口)。仅在编译时知道大小的情况下进行越界检查。示例:
from cppyy.gbl import Concrete
from array import array
c = Concrete()
c.array_method(array('d', [1., 2., 3., 4.]), 4)
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[10], line 1
----> 1 from cppyy.gbl import Concrete
2 from array import array
3 c = Concrete()
ModuleNotFoundError: No module named 'cppyy'
c.m_data[4] # static size is 4, so out of bounds
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[11], line 1
----> 1 c.m_data[4] # static size is 4, so out of bounds
NameError: name 'c' is not defined
cppyy 数组#
数组通过C++的低级视图对象来支持。只有在编译时知道大小或可以推断出大小时,这种方法才会有效。如果大小未知,则将大小设置为一个大整数(取决于数组元素的大小)以允许访问。然后由开发者确保不越界访问。对实例数组的支持有限,但在C++中应尽量避免使用这些:
cppyy.cppdef('std::string str_array[3][2] = {{"aa", "bb"}, {"cc", "dd"}, {"ee", "ff"}};')
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[12], line 1
----> 1 cppyy.cppdef('std::string str_array[3][2] = {{"aa", "bb"}, {"cc", "dd"}, {"ee", "ff"}};')
NameError: name 'cppyy' is not defined
type(cppyy.gbl.str_array[0][1])
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[13], line 1
----> 1 type(cppyy.gbl.str_array[0][1])
NameError: name 'cppyy' is not defined
cppyy.gbl.str_array[0][1]
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[14], line 1
----> 1 cppyy.gbl.str_array[0][1]
NameError: name 'cppyy' is not defined
cppyy.gbl.str_array[4][0]
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[15], line 1
----> 1 cppyy.gbl.str_array[4][0]
NameError: name 'cppyy' is not defined
cppyy 指针#
当C++代码采用指向特定内置类型的指针或引用类型(例如,无符号整数)时,类型必须完全匹配。cppyy支持标准模块ctypes和array提供的这些类型。使用对内置类型的引用的示例:
from ctypes import c_uint
u = c_uint(0)
c.uint_ref_assign(u, 42)
u.value
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[16], line 3
1 from ctypes import c_uint
2 u = c_uint(0)
----> 3 c.uint_ref_assign(u, 42)
4 u.value
NameError: name 'c' is not defined
对于对象,一个对象、指向对象的指针以及智能指针以相同的方式表示,同时自动应用必要的(解)引用。指针变量也通过引用绑定,因此C++或Python端的更新也会在另一端反映出来。
cppyy 枚举#
支持命名、匿名和类枚举。枚举的Python底层类型是实现相关的,甚至可能在同一编译器上对不同枚举有所不同。然而,通常这些类型是 int
或 unsigned int
,这会转换为 Python 的 int
或在 Python2 上的 long
,或者在 Python3 上的 class int
。与底层类型分开,所有枚举都有它们自己的 Python 类型,以允许它们用于模板实例化:
from cppyy.gbl import kBanana # classic enum, globally available
print(kBanana)
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[17], line 1
----> 1 from cppyy.gbl import kBanana # classic enum, globally available
2 print(kBanana)
ModuleNotFoundError: No module named 'cppyy'
cppyy.gbl.EFruit
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[18], line 1
----> 1 cppyy.gbl.EFruit
NameError: name 'cppyy' is not defined
print(cppyy.gbl.EFruit.kApple)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[19], line 1
----> 1 print(cppyy.gbl.EFruit.kApple)
NameError: name 'cppyy' is not defined
cppyy.gbl.E1
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[20], line 1
----> 1 cppyy.gbl.E1
NameError: name 'cppyy' is not defined
cppyy.gbl.NamedClassEnum.E1
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[21], line 1
----> 1 cppyy.gbl.NamedClassEnum.E1
NameError: name 'cppyy' is not defined