(4)python开发经验

发布于:2025-05-15 ⋅ 阅读:(12) ⋅ 点赞:(0)


更多精彩内容
👉内容导航 👈
👉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 的一些优点和缺点:

优点:

  1. 简单易用:pybind11 的语法简洁,易于上手。它提供了一种直观的方式将 C++ 代码暴露给 Python,这样即使是没有太多经验的用户也能够快速地编写绑定代码。
  2. 高性能:由于 pybind11 直接将 C++ 的类型映射到 Python 的类型,它可以提供接近于直接调用 C++ 函数的性能。
  3. 良好的 ABI 支持:pybind11 可以很好地处理 Python 的 ABI(Application Binary Interface),这意味着它在不同的 Python 版本之间具有很好的兼容性。
  4. 支持复杂的 C++ 特性:除了基本的数据类型之外,pybind11 还支持复杂的 C++ 特性,如 STL 容器、智能指针、异常处理等。
  5. 自动类型转换:pybind11 提供了自动的类型转换机制,使得在 C++ 和 Python 之间传递数据变得更加容易。

缺点:

  1. 学习曲线:虽然 pybind11 的语法简单,但要充分利用它的功能,还需要对 C++ 和 Python 的一些底层机制有一定的了解,这可能会形成一定的学习曲线。
  2. 调试复杂:当绑定的 C++ 代码出现问题时,调试可能会变得复杂,因为错误信息可能只出现在 Python 端,而实际的错误可能在 C++ 代码中。
  3. 跨平台一致性:虽然 pybind11 旨在提供跨平台的一致性,但在某些特殊情况下,可能仍然会遇到平台相关的兼容性问题。
  4. 依赖于 CMake:pybind11 建议使用 CMake 来构建项目,这对于那些不熟悉 CMake 的开发者来说可能会增加一些额外的负担。
  5. 编译时间:对于大型项目,编译时间可能会比较长,这取决于项目的复杂度和规模。
环境 说明
系统 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函数生成模块
    
    



网站公告

今日签到

点亮在社区的每一天
去签到