Python调用C++代码

本文探讨了Python调用C++代码的多种方法,包括使用ctypes、CFFI、Cython、Boost.Python和SWIG等工具。通过一个简单的加法函数示例,详细介绍了如何使用ctypes在Python中调用C/C++编译的动态链接库。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Python调用C++代码

今天在研究PyTorch中Tensor的一些操作的时候,发现其底层Tensor的操作都是用C++写的,并使用pybind11进行C++和Python的桥接。所以,我就想着探索一下Python中如何调用C++代码?

可行方案

其实,方案还是挺多的:

  • Python内置的ctypes接口(可以将C/C++代码编译为动态库,在Python中进行调用)
  • CFFI(提供了一种在Python代码中混合C代码的途径)
  • Cython (C后端版本的Python实现,建立了Python类型和C语言之间的映射关系,提供了使用Python代码调用C函数库的能力)
  • Boost.Python (提供手动导出C++代码接口的能力供Python调用)
  • SWIG(不止支持C/C++到Python的桥接,SWIG支持很多语言跟C/C++的桥接,是广泛使用的一种解决方案)

Hello Word示例

感觉ctypes简单很多,对于小型程序感觉还是挺友好的,所以该篇博客介绍一下使用ctypes调用C/C++的步骤。

编写C或者C++代码

头文件(test.h)

int sum(int, int);

C++代码(test.cpp)

// Windows需要__declspec(dllexport)申明
// extern "C"指示以C语言规范进行编译
#define DLLEXPORT extern "C"
DLLEXPORT int sum(int a, int b) {
    return a + b;
}

或者C代码(test.c)

// 同样的Windows在函数前面需要__declspec(dllexport)申明
int sum(int a, int b) {
    return a + b;
}

C代码编译成动态链接库

我使用的是macOS,选择使用gcc进行编译gcc -Wall -Wextra -O -ansi -pedantic -shared test.c -o test.so

在Python中调用

In [1]: from ctypes import cdll

In [2]: mydll = cdll.LoadLibrary('test.so')

In [3]: mydll.sum
Out[3]: <_FuncPtr object at 0x10f4cf688>

In [4]: mydll.sum(5, 2)
Out[4]: 7
### 在 Python调用 C++ 函数或类 #### 使用 `ctypes` 调用 C++ 动态库 (DLL) 为了使 `ctypes` 成功加载并调用 C++ 编写的动态链接库中的函数,需先将 C++ 代码编译为兼容的 DLL 文件,并导出所需的函数。由于 C++ 名称修饰问题,通常建议在 C++ 头文件中使用 extern "C" 来防止名称被修改。 ```cpp // mylib.cpp extern "C" { __declspec(dllexport) int add(int a, int b){ return a + b; } } ``` 接着,在 Python 环境下可以通过如下方式加载此 DLL 并调用其中定义的功能: ```python from ctypes import cdll # 加载 dll 文件 dll = cdll.LoadLibrary('mylib.dll') # 调用加法函数 result = dll.add(3, 4) print(f"The result is {result}") ``` 需要注意的是,当处理更复杂的 C++ 类型时(比如对象实例化),则可能需要额外的工作来适配数据结构以及管理内存分配等问题[^4]。 #### 使用 `cffi` 实现更高层次的封装 相比于 `ctypes`,`cffi` 提供了一个更加直观的方式来进行 C/C++ 接口描述。对于简单的例子来说,可以直接在线解析源码字符串;而对于大型项目,则可以从头文件自动生成绑定代码。 下面给出一个简单案例说明如何利用 `cffi` 访问上述相同的 C++ 函数: ```python import cffi ffibuilder = cffi.FFI() # 定义接口声明 ffibuilder.cdef(""" int add(int a, int b); """) # 设置要构建的目标平台上的共享库路径 if sys.platform.startswith('win'): ffibuilder.set_source("_mylib", r'#include "mylib.h"', libraries=['mylib']) else: ffibuilder.set_source("_mylib", '#include "mylib.h"', library_dirs=['.'], runtime_library_dirs=['.']) # 构建扩展模块 ffibuilder.compile(verbose=True) # 导入生成的模块并测试功能 from _mylib import lib as mylib res = mylib.add(7, 8) print(f"CFFI Result: {res}") ``` 这种方法不仅简化了跨语言间的通信流程,而且允许开发者更容易地维护和更新底层实现细节而无需频繁更改高层逻辑[^3].
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值