当前位置: 首页 > 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.jsqmd.com/news/43067/

相关文章:

  • 复杂状态与数据流管理:分布式定时任务系统的设计
  • 【第6章 字符串】Python 字符串常用操作完全教程(含代码演示)
  • DAG-有向无环图-拓扑排序
  • MySQL EXPLAIN中的key_len:精准掌握索引使用情况
  • 1090 : 分解因数 25-11-17
  • NOIP 模拟赛 9
  • Sora 2 Cameo多角色上传+Remix二创功能API接入教程,史低0.08/条
  • info linux
  • AWS云服务深度集成
  • httpd linux 启动
  • 浅谈 Manacher
  • 第28天(简单题中等题 二分查找)
  • 基于MIMO系统的SCMA稀疏码多址接入和MPA消息传递算法matlab仿真
  • Node.js服务稳定性保障:从热更新到高可用体系
  • 一次尝试,3个小时90元的主机游玩和F1电影
  • NOIP 模拟赛 8
  • 静态路由的配置
  • 读书笔记:“外部表”的进阶使用,它主要解决了三个核心问题:如何切换文件、多用户怎么办,以及一个非常酷的玩法——把系统命令变成表。
  • [CF 2166D] Marble Council
  • DP 复习
  • 一段话 UOJ
  • PG系列:在 ​​psql​​ 客户端中定义参数与动态赋值
  • CF1375G Tree Modification 题解
  • AI评价11月17号
  • 避雷:aicodemirror.com --- 酒干倘卖无
  • 9-线性学习
  • AT AGC003 题解
  • Oracle故障处理:aix 5.3 ml6安装10.2.0.1 rac报错
  • Hive SQL循环与MapReduce的关系
  • 《算 设》学