更多精彩内容 |
---|
👉内容导航 👈 |
👉Qt开发 👈 |
👉python开发 👈 |
1 使用ctypes库调用
- 说明:ctypes是一个Python内置的库,可以提供C兼容的数据类型,并允许调用动态链接库中的函数。它允许Python直接与C的共享库(.dll文件在Windows系统中,.so文件在Linux系统中)进行交互。
- 优点:
- 不需要编译Python扩展模块,使用简单。
- 可以直接加载和调用C++编写的函数。
- 缺点:
- 性能上不如专门设计的Python-C++绑定。
- 对C++代码的复杂性支持有限,仅适用于简单的函数调用。
- 需要手动处理数据类型转换,容易出错。
环境 | 说明 |
---|---|
系统 | windows11 |
编译器 | msvc2017 |
python | 3 |
c++代码
test.h
#ifndef TEST_H #define TEST_H extern "C" // 这里是关键,声明C接口,防止C++编译器对函数名进行修饰 { // 导出函数声明,如果是gcc、mingw编译器则去掉 __declspec(dllexport) __declspec(dllexport) int add(int a, int b); } #endif /* TEST_H */
test.cpp
#include "test.h" int add(int a, int b) { return a + b; }
CMakeLists.txt
cmake_minimum_required(VERSION 3.15) project(test) set(SOURCE test.h test.cpp) add_library(${PROJECT_NAME} SHARED ${SOURCE}) # 设置为动态库
编译后会生成test.lib、test.dll两个文件;
如果使用mingw编译器编译会生成libtest.dll.a、libtest.dll两个文件,使用libtest.dll。
python调用dll
将test.dll文件放到main.py所在路径下。
main.py
from ctypes import cdll lib = cdll.LoadLibrary('./test.dll') # 判断是否加载成功 if lib: print("加载成功") else: print("加载失败") # 调用简单函数 result = lib.add(3, 5) print(result) # 输出8
注意: __declspec(dllexport)
是MSVC编译器特有的关键词,用于Windows平台的DLL导出。如果你使用的是GCC编译器(通常在Linux或macOS上使用),则不需要使用 __declspec(dllexport)
2 使用pybind11
pybind11 是一个用于方便地将 C++ 代码绑定到 Python 的库,它使得在 Python 中调用 C++ 函数、使用 C++ 类和数据结构变得简单。以下是 pybind11 的一些优点和缺点:
优点:
- 简单易用:pybind11 的语法简洁,易于上手。它提供了一种直观的方式将 C++ 代码暴露给 Python,这样即使是没有太多经验的用户也能够快速地编写绑定代码。
- 高性能:由于 pybind11 直接将 C++ 的类型映射到 Python 的类型,它可以提供接近于直接调用 C++ 函数的性能。
- 良好的 ABI 支持:pybind11 可以很好地处理 Python 的 ABI(Application Binary Interface),这意味着它在不同的 Python 版本之间具有很好的兼容性。
- 支持复杂的 C++ 特性:除了基本的数据类型之外,pybind11 还支持复杂的 C++ 特性,如 STL 容器、智能指针、异常处理等。
- 自动类型转换:pybind11 提供了自动的类型转换机制,使得在 C++ 和 Python 之间传递数据变得更加容易。
缺点:
- 学习曲线:虽然 pybind11 的语法简单,但要充分利用它的功能,还需要对 C++ 和 Python 的一些底层机制有一定的了解,这可能会形成一定的学习曲线。
- 调试复杂:当绑定的 C++ 代码出现问题时,调试可能会变得复杂,因为错误信息可能只出现在 Python 端,而实际的错误可能在 C++ 代码中。
- 跨平台一致性:虽然 pybind11 旨在提供跨平台的一致性,但在某些特殊情况下,可能仍然会遇到平台相关的兼容性问题。
- 依赖于 CMake:pybind11 建议使用 CMake 来构建项目,这对于那些不熟悉 CMake 的开发者来说可能会增加一些额外的负担。
- 编译时间:对于大型项目,编译时间可能会比较长,这取决于项目的复杂度和规模。
环境 | 说明 |
---|---|
系统 | windows11 |
编译器 | msvc2017-64 注意:如果使用mingw编译则python可能无法使用,python一般是使用msvc生成 |
使用
git clone https://github.com/pybind/pybind11.git
下载源码;将pybind11文件夹放到C++工程路径下;
test.cpp
#include <pybind11/pybind11.h> int add(int a, int b) { return a + b; } namespace py = pybind11; // 这里的命名空间别名是 py PYBIND11_MODULE(test, m) { // def用法:def(name, function, doc_string) // name: 在Python中调用的函数名 // function: 要绑定的C++函数 // doc_string: 函数的文档字符串 m.def("add", &add, "A function which adds two numbers"); }
CMakeLists.txt
cmake_minimum_required(VERSION 3.15) project(test) add_subdirectory(./pybind11) # 这里是添加pybind11的子目录 set(SOURCE test.cpp) pybind11_add_module(${PROJECT_NAME} ${SOURCE}) # 使用pybind11_add_module函数生成模块
编译后会生成一个
test.cp313-win_amd64.pyd
文件,将test.cp313-win_amd64.pyd放到main.py路径下。main.py
import test print(test.add(2,3))
或者使用
pip install pybind11
安装库;CMakeLists.txt如下所示:
cmake_minimum_required(VERSION 3.15) project(test) # 寻找python库,Interpreter:表示查找 Python 解释器,Development:表示查找 Python 开发包 find_package(Python COMPONENTS Interpreter Development) # 查找pybind11包,并设置路径 find_package(pybind11 PATHS "E:/py/PythonProject1/.venv/Lib/site-packages/pybind11/share/cmake/" REQUIRED) set(SOURCE test.cpp) pybind11_add_module(${PROJECT_NAME} ${SOURCE}) # 使用pybind11_add_module函数生成模块