cppyy 顶层#
cppyy
在模块级别提供了一些辅助函数,这些函数提供(直接)访问 Cling 解释器的功能(任何 C++ 代码总是通过全局命名空间 cppyy.gbl
访问)。文档中会频繁使用这些辅助函数,因此它们首先在这里列出,但通过 Python 解释器本身使用 help()
函数可以更方便地访问它们的文档。
import cppyy
help(cppyy)
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[1], line 1
----> 1 import cppyy
2 help(cppyy)
ModuleNotFoundError: No module named 'cppyy'
cppyy 加载 C++#
C++ 代码可以作为文本加载并即时编译(JIT),或者提前编译并以共享库的形式提供。在后一种情况下,还需要加载 C++ 头文件以向 Cling 声明类、函数和变量。除了头文件,还可以使用预编译代码;特别是所有标准 C++ 头文件和一些系统头文件在启动时都已预编译。cppyy
提供了以下辅助工具来加载 C++ 代码:
cppdef
: 直接访问解释器。此函数接受 C++ 声明作为字符串并即时编译(JIT)它们(在实际使用之前不会创建绑定)。代码被加载到全局范围内,因此从一个cppdef
调用到下一个调用,任何先前加载的代码以及所有已通过预编译头文件加载的标准 C++ 头文件都是可用的。示例:
cppyy.cppdef(r"""\
void hello() {
std::cout << "Hello, World!" << std::endl;
}""")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[2], line 1
----> 1 cppyy.cppdef(r"""\
2 void hello() {
3 std::cout << "Hello, World!" << std::endl;
4 }""")
NameError: name 'cppyy' is not defined
cppyy.gbl.hello()
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[3], line 1
----> 1 cppyy.gbl.hello()
NameError: name 'cppyy' is not defined
cppexec
: 直接访问解释器。此函数接受 C++ 语句作为字符串,即时编译并执行它们。就像cppdef
一样,执行在全局范围内进行,所有先前加载的代码都是可用的。如果语句是声明,效果与cppdef
相同,但cppexec
也接受可执行的代码行。示例:
cppyy.cppexec(r"""std::string hello = "Hello, World!";""")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[4], line 1
----> 1 cppyy.cppexec(r"""std::string hello = "Hello, World!";""")
NameError: name 'cppyy' is not defined
cppyy.cppexec("std::cout << hello << std::endl;")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[5], line 1
----> 1 cppyy.cppexec("std::cout << hello << std::endl;")
NameError: name 'cppyy' is not defined
include
: 将声明加载到解释器中。此函数接受来自文件的 C++ 声明,通常是头文件。文件通过给定给 Cling 的包含路径来定位。示例:
cppyy.include("vector") # equivalent to "#include <vector>"
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[6], line 1
----> 1 cppyy.include("vector") # equivalent to "#include <vector>"
NameError: name 'cppyy' is not defined
c_include
: 将声明加载到解释器中。此函数接受来自文件的 C++ 声明,通常是头文件。名称修饰是 C 和 C++ 代码之间的一个重要区别。使用c_include
而不是include
可以防止名称修饰。
load_library
: 将编译好的 C++ 代码加载到解释器中。此函数接受共享库的名称,并将其加载到当前进程中,将所有外部符号暴露给 Cling。库通过给定给 Cling 的加载路径来定位,可以通过“-L
”编译器标志或动态搜索路径环境变量(系统依赖)来实现。任何将符号引入进程的方法(包括常规链接,例如在 C++ 应用程序中嵌入 Python 时)都适合用于暴露符号。作为load_library
的替代方案,例如可以使用ctypes.CDLL
,但该函数并非在所有平台上都支持动态加载路径。
如果在使用上述辅助函数中的任何一个对 C++ 代码进行即时编译(JIT)时发生编译错误,会引发 Python SyntaxError
异常。如果发生编译警告,则会发出 Python 警告。
cppyy 配置 Cling#
当加载模块时,通常方便地为 Cling 添加额外的搜索路径以查找头文件和库(Python 没有标准位置来放置头文件和库,但通常可以根据模块的位置推断出它们的位置,即其 __file__
属性)。cppyy
提供了以下两个辅助函数:
add_include_path
: 为 Cling 添加额外的路径以查找头文件。add_library_path
: 为 Cling 添加额外的路径以查找库。
这两个函数都接受一个字符串(单个路径)或一个列表(用于添加多个路径)。允许使用相对路径,但建议使用绝对路径。
cppyy C++ 语言#
一些 C++ 编译时特性在 Python 中没有等效项。相反,提供了便利函数:
sizeof
: 接受一个代理的 C++ 类型或其名称作为字符串,并返回存储大小(以char
为单位)。typeid
: 接受一个代理的 C++ 类型或其名称作为字符串,并返回 C++ 运行时类型信息(RTTI)。nullptr
: C++NULL
。
cppyy
预处理器#
在 Python 端,预处理器宏(#define
)不可用,因为没有可用的类型信息。然而,它们通常用于常量数据(例如标志或数字;请注意,现代 C++ 推荐使用 const
和 constexpr
)。在限制范围内,表示常量数据的宏可以通过 macro
辅助函数访问。示例:
import cppyy
cppyy.cppdef('#define HELLO "Hello, World!"')
---------------------------------------------------------------------------
ModuleNotFoundError Traceback (most recent call last)
Cell In[7], line 1
----> 1 import cppyy
2 cppyy.cppdef('#define HELLO "Hello, World!"')
ModuleNotFoundError: No module named 'cppyy'
cppyy.macro("HELLO")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
Cell In[8], line 1
----> 1 cppyy.macro("HELLO")
NameError: name 'cppyy' is not defined