当前位置: 首页 > news >正文

Python调用C++代码

Python调用C++代码

1. extern "C" {} 包裹导出函数

// C++ 中存在名称修饰,通过 extern "C" {} 将C++函数导出为C函数
// 1. 为类的每个函数创建C风格接口,第一个参数为对象指针
// 2. 提供 create(构造) destroy(析构) 函数管理对象的生命周期
#include <string>// C++类定义
class Calculator {
private:
int base;
public:
Calculator(int b) : base(b) {}
int add(int a) { return base + a; }
std::string greet(const std::string& name) { return "Hello, " + name; }
};// C风格函数
extern "C" {// 创建对象(对应构造函数)
Calculator* Calculator_create(int base) {
return new Calculator(base);
}// 销毁对象(对应析构函数)
void Calculator_destroy(Calculator* obj) {
delete obj;
}// 封装成员函数
int Calculator_add(Calculator* obj, int a) {
return obj->add(a);
}// 字符串处理需要特殊转换(C++ string -> char*)
const char* Calculator_greet(Calculator* obj, const char* name) {
static std::string result;  // 注意:静态变量在多线程中不安全
result = obj->greet(std::string(name));
return result.c_str();
}}

2. 将C++代码编译为动态库

# 使用C++编译器,保留 -f PIC -shared 参数生成位置无关的动态库
g++ -shared -fPIC -o libcalc.so example.cpp

3. 使用python的ctypes库调用动态库(加载动态库 -> 定义C函数的输入参数与返回参数 -> 调用动态库函数)

  • 用 c_void_p 类型存储C++对象的指针
  • 字符串通过bytes类型转换(encode/decode)
  • 实现 del 方法自动释放C++对象,避免内存泄漏
import ctypes
import osclass CalculatorWrapper:"""C++ Calculator类的Python封装器"""def __init__(self):# 加载动态库self.lib = self._load_library()# 配置C接口函数原型self._setup_functions()# 存储C++对象指针self.obj_ptr = Nonedef _load_library(self):"""根据操作系统加载对应的库文件"""try:if os.name == "nt":return ctypes.CDLL("./calc.dll")elif os.name == "posix":return ctypes.CDLL("./libcalc.so")else:raise OSError("不支持的操作系统")except OSError as e:raise RuntimeError(f"加载库失败: {e}")def _setup_functions(self):"""定义C接口函数的参数类型和返回值类型"""# 创建对象self.lib.Calculator_create.argtypes = [ctypes.c_int]self.lib.Calculator_create.restype = ctypes.c_void_p  # 返回对象指针# 销毁对象self.lib.Calculator_destroy.argtypes = [ctypes.c_void_p]self.lib.Calculator_destroy.restype = None# 加法函数self.lib.Calculator_add.argtypes = [ctypes.c_void_p, ctypes.c_int]self.lib.Calculator_add.restype = ctypes.c_int# 字符串问候函数self.lib.Calculator_greet.argtypes = [ctypes.c_void_p, ctypes.c_char_p]self.lib.Calculator_greet.restype = ctypes.c_char_pdef create(self, base_value):"""创建C++ Calculator实例"""self.obj_ptr = self.lib.Calculator_create(base_value)if not self.obj_ptr:raise RuntimeError("创建C++对象失败")def add(self, a):"""调用加法方法"""self._check_object()return self.lib.Calculator_add(self.obj_ptr, a)def greet(self, name):"""调用问候方法(处理字符串转换)"""self._check_object()# Python字符串转C字符串(bytes类型)c_name = name.encode('utf-8')result_ptr = self.lib.Calculator_greet(self.obj_ptr, c_name)# C字符串转Python字符串return result_ptr.decode('utf-8')def _check_object(self):"""检查对象是否已创建"""if not self.obj_ptr:raise RuntimeError("请先调用create()创建对象")def __del__(self):"""对象销毁时自动释放C++资源"""if self.obj_ptr:self.lib.Calculator_destroy(self.obj_ptr)if __name__ == "__main__":try:calc = CalculatorWrapper()calc.create(100)  # 初始化base值为100print(f"100 + 50 = {calc.add(50)}")  # 输出150print(calc.greet("C++"))  # 输出"Hello, Python"except Exception as e:print(f"错误: {e}")
http://www.zskr.cn/news/52500.html

相关文章:

  • MySQL EXPLAIN中的key_len:精准掌握索引使用情况
  • AWS云服务深度集成
  • httpd linux 启动
  • Node.js服务稳定性保障:从热更新到高可用体系
  • PG系列:在 ​​psql​​ 客户端中定义参数与动态赋值
  • 欢迎关注我的公众号和B站
  • 11/17
  • linux 下中文字体安装.ttf 格式
  • 2025 年锚具厂家 TOP 企业品牌推荐排行榜,桥梁伸缩缝 / 道路伸缩缝 / 梳齿板伸缩缝推荐这十家公司!
  • 2025-11-17
  • 论文速读 | 2025年11月
  • halt linux
  • hadoop linux 安装
  • 解决罗技M590右键必须用力才能使用的问题
  • sequence 题解
  • 20232410 2025-2026-1 《网络与系统攻防技术》实验六实验报告
  • FastAPI Test Project
  • React Scheduler(调度器)
  • 2025年11月学习机榜单:双线提分机型领衔,十大高性价比之选
  • vue2和vue3声明式和命令时的区别
  • 3D 文件类型,怎么在线查看编辑STL/AMF/OBJ/stp/fbx/ply转换
  • 022304105叶骋恺数据采集第三次作业
  • 2025 ICPC 南京区域赛 CFGIJ
  • wps office 2023专业增强版
  • 周作业 44
  • 不是插件,这款公众号排版让你的文章颜值翻倍
  • gdb 安装linux
  • g for linux
  • 二分图的判定
  • 人工智能之编程基础 Python 入门:第九章 模块与包