cppyy 顶层#

cppyy 在模块级别提供了一些辅助函数,这些函数提供(直接)访问 Cling 解释器的功能(任何 C++ 代码总是通过全局命名空间 cppyy.gbl 访问)。文档中会频繁使用这些辅助函数,因此它们首先在这里列出,但通过 Python 解释器本身使用 help() 函数可以更方便地访问它们的文档。

import cppyy
help(cppyy)
Help on package cppyy:

NAME
    cppyy - Dynamic C++ bindings generator.

DESCRIPTION
    This module provides dynamic bindings to C++ through Cling, the LLVM-based C++
    interpreter, allowing interactive mixing of Python and C++. Example:

        >>> import cppyy
        >>> cppyy.cppdef("""
        ... class MyClass {
        ... public:
        ...     MyClass(int i) : m_data(i) {}
        ...     int m_data;
        ... };""")
        True
        >>> from cppyy.gbl import MyClass
        >>> m = MyClass(42)
        >>> cppyy.cppdef("""
        ... void say_hello(MyClass* m) {
        ...     std::cout << "Hello, the number is: " << m->m_data << std::endl;
        ... }""")
        True
        >>> MyClass.say_hello = cppyy.gbl.say_hello
        >>> m.say_hello()
        Hello, the number is: 42
        >>> m.m_data = 13
        >>> m.say_hello()
        Hello, the number is: 13
        >>>

    For full documentation, see:
       https://cppyy.readthedocs.io/

PACKAGE CONTENTS
    __pyinstaller (package)
    _cpython_cppyy
    _pypy_cppyy
    _pythonization
    _stdcpp_fix
    _typemap
    _version
    interactive
    ll
    numba_ext
    reflex
    types

SUBMODULES
    py

FUNCTIONS
    add_autoload_map(fname)
        Add the entries from a autoload (.rootmap) file to Cling.

    add_include_path(path)
        Add a path to the include paths available to Cling.

    add_library_path(path)
        Add a path to the library search paths available to Cling.

    c_include(header)
        Load (and JIT) header file <header> into Cling.

    cppdef(src)
        Declare C++ source <src> to Cling.

    cppexec(stmt)
        Execute C++ statement <stmt> in Cling's global scope.

    include(header)
        Load (and JIT) header file <header> into Cling.

    load_library(name)
        Explicitly load a shared library.

    macro(cppm)
        Attempt to evalute a C/C++ pre-processor macro as a constant

    multi(*bases)
        Resolve metaclasses for multiple inheritance.

    set_debug(enable=True)
        Enable/disable debug output.

    sizeof(tt)
        Returns the storage size (in chars) of C++ type <tt>.

    typeid(tt)
        Returns the C++ runtime type information for type <tt>.

DATA
    __all__ = ['cppdef', 'cppexec', 'macro', 'include', 'c_include', 'load...
    __warningregistry__ = {'version': 16}
    nullptr = nullptr

VERSION
    3.1.2

AUTHOR
    Wim Lavrijsen <WLavrijsen@lbl.gov>

FILE
    /media/pc/data/lxw/envs/anaconda3x/envs/xxx/lib/python3.12/site-packages/cppyy/__init__.py
/media/pc/data/lxw/envs/anaconda3x/envs/xxx/bin/python3.12: not an ELF file.

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;
}""")
True
cppyy.gbl.hello()
Hello, World!
  • cppexec: 直接访问解释器。此函数接受 C++ 语句作为字符串,即时编译并执行它们。就像 cppdef 一样,执行在全局范围内进行,所有先前加载的代码都是可用的。如果语句是声明,效果与 cppdef 相同,但 cppexec 也接受可执行的代码行。示例:

cppyy.cppexec(r"""std::string hello = "Hello, World!";""")
True
cppyy.cppexec("std::cout << hello << std::endl;")
Hello, World!
True
  • include: 将声明加载到解释器中。此函数接受来自文件的 C++ 声明,通常是头文件。文件通过给定给 Cling 的包含路径来定位。示例:

cppyy.include("vector")   # equivalent to "#include <vector>"
True
  • 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++ 推荐使用 constconstexpr)。在限制范围内,表示常量数据的宏可以通过 macro 辅助函数访问。示例:

import cppyy
cppyy.cppdef('#define HELLO "Hello, World!"')
True
cppyy.macro("HELLO")
'Hello, World!'