cppyy: 一个强大的 Python-C++ 互操作性库

目录

1.简介

2.基本原理

3.安装与集成

4.用法示例

5.高级特性

6.优缺点分析

7.常见问题


1.简介

cppyy 是一款基于 Clang/LLVMCling 实现的 C++ 与 Python 双向交互库,核心优势是无需手写包装代码,即可实现 Python 对 C++ 代码的直接调用,以及 C++ 对 Python 对象的无缝访问,支持 C++11/14/17/20 等现代标准,适配跨平台开发(Windows/Linux/macOS)。

核心特征:

1.运行时绑定

  • 无需预编译包装代码

  • 动态加载 C++ 库

  • 实时反射 C++ 类型

2.自动类型转换

  • 基本类型自动转换

  • STL 容器支持

  • 智能指针处理

3.高性能

  • 直接调用 C++,无需中间层

  • 与原生 C++ 性能相近

2.基本原理

cppyy 的底层依赖两大核心组件,实现了 C++ 与 Python 的深度绑定:

  • Clang/LLVM:负责解析 C++ 代码生成抽象语法树(AST),完成类型检查与代码分析,支持复杂的 C++ 特性(模板、命名空间、重载等)。
  • Cling:C++ 交互式解释器,提供运行时的 C++ 代码编译与执行能力,让 Python 可以动态加载并调用 C++ 代码。
  • 绑定机制:通过自动生成的类型桥接层,将 C++ 的类、函数、模板等映射为 Python 可调用的对象,同时支持 C++ 侧直接操作 Python 的列表、字典、函数等对象。

3.安装与集成

1.pip 快速安装(推荐)

适用于大部分场景,自动匹配系统环境的预编译包:

cpp 复制代码
# 基础版
pip install cppyy

# 完整版(含额外工具,如 cppyy-cling 解释器)
pip install cppyy-full

2.源码编译安装(适配自定义 LLVM 版本)

适合需要对接特定 Clang/LLVM 版本的场景(如与项目中的 LLVM 依赖一致):

1)安装依赖

Linux (Ubuntu/Debian):

cpp 复制代码
sudo apt-get install llvm-dev clang-dev libclang-dev cmake g++

Windows:安装 Visual Studio(需勾选 C++ 开发工具) + CMake

macOS:

cpp 复制代码
brew install llvm clang cmake

2)编译安装 cppyy:

cpp 复制代码
git clone https://github.com/wlav/cppyy.git
cd cppyy
mkdir build && cd build
cmake .. -DCMAKE_INSTALL_PREFIX=<安装路径>
make -j$(nproc)
make install

4.用法示例

1.Python 调用 C++ 函数 / 类

示例 1:调用简单 C++ 函数

cpp 复制代码
import cppyy

# 直接定义 C++ 代码并编译
cppyy.cppdef("""
#include <iostream>
void hello_cpp(const std::string& msg) {
    std::cout << "C++ says: " << msg << std::endl;
}

int add(int a, int b) {
    return a + b;
}
""")

# 调用 C++ 函数
cppyy.gbl.hello_cpp("Hello from Python!")
result = cppyy.gbl.add(10, 20)
print(f"Python gets result: {result}")  # 输出 30

示例 2:调用 C++ 类与模板

cpp 复制代码
import cppyy

cppyy.cppdef("""
#include <vector>
class MyClass {
private:
    int m_data;
public:
    MyClass(int data) : m_data(data) {}
    int get_data() const { return m_data; }
    void set_data(int data) { m_data = data; }
};
""")

# 实例化 C++ 类
obj = cppyy.gbl.MyClass(100)
print(obj.get_data())  # 输出 100
obj.set_data(200)
print(obj.get_data())  # 输出 200

# 调用 C++ STL 模板(std::vector)
vec = cppyy.gbl.std.vector[int]()
vec.push_back(1)
vec.push_back(2)
print(f"Vector size: {vec.size()}")  # 输出 2
print(f"First element: {vec[0]}")    # 输出 1

2.C++ 调用 Python 代码

cppyy 支持在 C++ 中直接导入 Python 模块、调用函数、操作对象:

cpp 复制代码
import cppyy
import math  # 待 C++ 调用的 Python 模块

# 将 Python 模块/函数暴露给 C++
cppyy.gbl.math = math
cppyy.gbl.python_abs = abs

# 在 C++ 中调用 Python 函数
cppyy.cppdef("""
void call_python_funcs() {
    // 调用 Python math 模块的 sqrt 函数
    double res = math.sqrt(16.0);
    std::cout << "Python sqrt(16) = " << res << std::endl;

    // 调用 Python 内置 abs 函数
    int abs_res = python_abs(-10);
    std::cout << "Python abs(-10) = " << abs_res << std::endl;
}
""")

# 执行 C++ 中的调用逻辑
cppyy.gbl.call_python_funcs()

3.回调函数(Python 到 C++)

cpp 复制代码
import cppyy

cppyy.cppdef("""
    #include <functional>
    #include <vector>
    
    void apply_function(const std::vector<double>& vec, 
                        std::function<double(double)> func) {
        for (auto& v : vec) {
            std::cout << func(v) << std::endl;
        }
    }
""")

def python_func(x):
    return x * x + 2 * x + 1

vec = cppyy.gbl.std.vector[float]([1.0, 2.0, 3.0, 4.0])
cppyy.gbl.apply_function(vec, python_func)

4.内存管理

cpp 复制代码
import cppyy

cppyy.cppdef("""
    class Resource {
        int* data;
    public:
        Resource(size_t size) {
            data = new int[size];
        }
        ~Resource() {
            delete[] data;
        }
    };
""")

# 自动内存管理
res = cppyy.gbl.Resource(100)

# 手动控制
ptr = cppyy.bind_object(cppyy.gbl.Resource(200), cppyy.gbl.Resource)
# 当不再需要时
cppyy.destruct(ptr)

5.高级特性

1.集成 CMake 项目

对于 C++ 项目,可通过 CMake 配置 cppyy 的头文件与库路径,实现 Python 对项目代码的调用:

cpp 复制代码
cmake_minimum_required(VERSION 3.15)
project(cppyy_demo)

# 查找 cppyy 依赖
find_package(cppyy REQUIRED)

# 添加 C++ 源文件
add_library(mylib SHARED mylib.cpp)

# 链接 cppyy 库
target_link_libraries(mylib PRIVATE cppyy)

# 导出头文件路径(供 Python 侧 include)
target_include_directories(mylib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})

Python 侧通过 cppyy.includecppyy.load_library 加载:

cpp 复制代码
import cppyy
cppyy.include("mylib.h")  # 导入项目头文件
cppyy.load_library("./libmylib.so")  # Linux 动态库
# cppyy.load_library("./mylib.dll")  # Windows 动态库

# 调用项目中的 C++ 接口
cppyy.gbl.mylib_func()

2.支持 Qt 框架绑定

针对 Qt 项目,cppyy 可直接解析 Qt 的类与信号槽机制(需确保 Qt 头文件可被 Clang 找到):

cpp 复制代码
import cppyy
cppyy.add_include_path("/usr/include/qt6")  # Qt 头文件路径
cppyy.include("QString")
cppyy.include("QPushButton")

# 实例化 Qt 类
qstr = cppyy.gbl.QString("Hello Qt")
print(qstr.toStdString())  # 输出 Hello Qt

3.兼容 C++20 特性

cppyy 支持 C++20 的协程、概念、范围等特性,示例如下:

cpp 复制代码
import cppyy

cppyy.cppdef("""
#include <coroutine>
#include <iostream>

// C++20 协程示例
struct MyCoroutine {
    struct promise_type {
        MyCoroutine get_return_object() { return {}; }
        std::suspend_never initial_suspend() { return {}; }
        std::suspend_never final_suspend() noexcept { return {}; }
        void return_void() {}
        void unhandled_exception() {}
    };
};

MyCoroutine coro_func() {
    std::cout << "C++20 coroutine running" << std::endl;
    co_return;
}
""")

# 调用 C++20 协程函数
cppyy.gbl.coro_func()

4.性能优化

  • 减少类型转换开销 :使用 cppyy.bind_object 将 C++ 对象直接绑定到 Python,避免拷贝。
  • 预编译 C++ 代码 :通过 cppyy.compile 预编译高频调用的 C++ 代码,提升运行速度。

6.优缺点分析

优点 缺点
无需手写包装代码,自动完成 C++ 与 Python 绑定 对复杂宏定义、部分模板特化的支持有限
支持现代 C++ 特性(C++11-C++20) 启动速度略慢(首次解析 C++ 代码需编译时间)
双向交互能力强,C++ 可直接调用 Python 代码 调试难度较高,C++ 侧错误在 Python 中定位不直观
跨平台兼容性好,适配 Windows/Linux/macOS 对第三方库的依赖需要手动配置头文件和库路径

7.常见问题

  • 找不到头文件 :通过 cppyy.add_include_path 添加头文件路径,例如 cppyy.add_include_path("/usr/include")
  • 动态库加载失败 :确保动态库路径正确,且库与当前 Python 版本(32/64 位)一致;Linux 下可通过 LD_LIBRARY_PATH 设置库路径。
  • 模板函数调用报错 :显式指定模板参数类型,例如 cppyy.gbl.std.vector[int]() 而非 cppyy.gbl.std.vector()
相关推荐
寻寻觅觅☆8 小时前
东华OJ-基础题-106-大整数相加(C++)
开发语言·c++·算法
YJlio8 小时前
1.7 通过 Sysinternals Live 在线运行工具:不下载也能用的“云端工具箱”
c语言·网络·python·数码相机·ios·django·iphone
fpcc8 小时前
并行编程实战——CUDA编程的Parallel Task类型
c++·cuda
l1t9 小时前
在wsl的python 3.14.3容器中使用databend包
开发语言·数据库·python·databend
赶路人儿9 小时前
Jsoniter(java版本)使用介绍
java·开发语言
ceclar12310 小时前
C++使用format
开发语言·c++·算法
山塘小鱼儿10 小时前
本地Ollama+Agent+LangGraph+LangSmith运行
python·langchain·ollama·langgraph·langsimth
码说AI10 小时前
python快速绘制走势图对比曲线
开发语言·python
Gofarlic_OMS10 小时前
科学计算领域MATLAB许可证管理工具对比推荐
运维·开发语言·算法·matlab·自动化