cppyy 字符串/Unicode#

Python 和 C++ 都有核心类型来表示文本,这些类型应该可以自由互换。cppyy 使这在最常见情况下变得容易,同时在必要时允许自定义以涵盖各种不同的用例(如不同的编解码器)。除了这些核心类型外,还有一系列其他字符类型,从 const char*std::wstringbytes,它们的使用较少,但也得到了完全支持。

cppyy std::string#

C++ 的核心类型 std::string 被视为 Python 的 str 等价物,即使纯粹从实现角度来看,它更类似于 bytes:实际上,C++ 程序员会使用 std::string 的地方,Python 开发者会使用 str (反之亦然),而不是 bytes

然而,Python 的 strunicode,而 std::string 是基于字符的,因此转换需要编码或解码。为了支持不同的编码,cppyy 推迟了在两种类型之间的隐式转换,直到强制进行转换时,此时默认将 std::string 视为基于 ASCII,并将 str 使用 UTF-8 编解码器。为此,绑定的 std::string 已被 python 化,以允许其作为适当的本地上下文中的多种用途的替代品。

特别是,有时(例如对于接受非 const 引用或指向非 const std::string 变量的指针的函数参数),有必要使用实际的 std::string 实例以允许就地修改。然后这些 python 化操作允许在期望 str 的地方使用它们。例如:

import cppyy
cppyy.cppexec("std::string gs;")
---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Cell In[1], line 1
----> 1 import cppyy
      2 cppyy.cppexec("std::string gs;")

ModuleNotFoundError: No module named 'cppyy'
cppyy.gbl.gs = "hello"
cppyy.gbl.gs
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[2], line 1
----> 1 cppyy.gbl.gs = "hello"
      2 cppyy.gbl.gs

NameError: name 'cppyy' is not defined
type(cppyy.gbl.gs)   # C++ std::string type
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[3], line 1
----> 1 type(cppyy.gbl.gs)   # C++ std::string type

NameError: name 'cppyy' is not defined
d = {"hello": 42}    # dict filled with str
d[cppyy.gbl.gs]      # drop-in use of std::string -> str
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
Cell In[4], line 2
      1 d = {"hello": 42}    # dict filled with str
----> 2 d[cppyy.gbl.gs]      # drop-in use of std::string -> str

NameError: name 'cppyy' is not defined

为了处理除UTF-8之外的编解码器,std::string 的 python 化增加了 decode 方法,其签名与 bytes 的相应方法相同。如果已知某个特定的 C++ 函数始终返回代表 unicodestd::string,且使用非 UTF-8 的编解码器,则可以将其显式 python 化以使用该编解码器进行转换。

cppyy std::string_view#

可以从 Python str 构建一个基于字符的 std::string_view,但需要将 unicode 对象编码,默认情况下选择 UTF-8。如果 str 中的所有字符都来自 ASCII 集,这将得到预期的结果,但在其他情况下建议在 Python 端进行编码并传递结果 bytes 对象。

cppyy std::wstring\#

C++ 的“宽”字符串,std::wstring,基于 wchar_t,这是一个不太便携的字符类型,因为它的大小可以是 2 字节或 4 字节,取决于平台。cppyy 直接支持 std::wstring ,使用 Python 的 C-API 提供的 wchar_t 数组转换。

cppyy const char*#

C 表示文本的 const char* 存在两个问题:它不表达所有权;长度是隐式的,即直到第一个 '\0' 出现为止。在一定程度上可以改善第一个问题:在某些情况下可以推断出所有者。特别是,如果 C 字符串是从Python str 设置的,后者拥有内存,绑定代理前者又拥有(未转换的) str 实例。然而,如果 const char* 的内存在 C/C++ 中分配,内存管理必然完全是手动的。另一方面,仅在固定数组的情况下才能知道长度。然而即便如此,更常见的情况是使用固定数组作为缓冲区,实际字符串仍然只延伸到 '\0' 字符,因此这样假设。(C++ 的 `std::string没有这些问题,只要有选择就应该始终优先使用。)

cppyy char*#

C表示的字符数组 char* 具有 const char* 的所有问题,但除此之外还经常用作“8位int的数据数组”。

cppyy 字符类型#

cppyy 直接支持以下字符类型,既可以作为单个变量也可以作为数组形式:char, signed char, unsigned char, wchar_t, char16_tchar32_t