使用pybind11将c++扩展为python

一、在VS中直接生成pyd

参考:

pybind11在Windows下的使用 - 酱_油 - 博客园 (cnblogs.com)

编写 Python 的 C++ 扩展 - Visual Studio (Windows) | Microsoft Learn

缺点:生成的pyd不能直接用于不同系统

  1. 首先安装pybind11并在VS中配置

安装pybind11:mirrors / pybind / pybind11 · GitCode

配置:正常创建项目并添加cpp文件后,在项目的属性中设置如下:

E:\Installed\Anaconda3\include

E:\Installed\pybind11-master\include

E:\Installed\Anaconda3\libs

python37.lib

python3.lib

2.在原有的c++代码基础上添加头文件,如果需要路径传参,可以将原有main函数中的arg转化为普通函数的参数

#include <pybind11/pybind11.h>

int add(int x, int y) {
    return x + y;
}

3.使用PYBIND11_MODULE宏将C++函数包装为Python模块

PYBIND11_MODULE(example, m) {
    m.def("add", &add, "A function which adds two numbers");
}

其中,“example”是Python模块的名称(注意此名称要和项目名称保持一致),“m”是pybind11库中的一个module_对象,m.def函数用于将C++函数add包装为Python函数,并设置函数的文档字符串。

4.编译运行生成pyd文件,将pyd文件置于python项目中即可调用(如果修改了c++的函数后,要重新生成扩展库,如果c++源代码中调用了其他库,此时在pyd目录下还生成了其他dll等文件,一并复制到python项目中,下例在loopsubd文件夹中

import example
if __name__ == "__main__":
    x, y = 12, 2
    answer = example.add(x, y)
    print(f"In Python: int: {x} int {y} return val {answer}")


import loopsubd.loop_subdivision as loop_subdivision

if __name__ == "__main__":
    loop_subdivision.run("U","data/model_RZY/IOS_U_RZY.obj", "data/model_RZY/CBCT_U_RZY.obj","data/model_RZY/IOS_single_o/U/","data/model_RZY/CBCT_single_o/U/","data/model_RZY/CBCT_single_subdivision/","data/model_RZY/IOS_single_smooth/","data/model_RZY/CBCT_trans/match/","data/model_RZY/CBCT_single_trans/match/","data/model_RZY/CBCT_nricp/IOS/","data/model_RZY/CBCT_nricp/CBCT/","data/model_RZY/RZY_alveolar_bone_U.obj","data/model_RZY/bone_trans/")

二、在pycharm中生成pyd

参考:

pybind11—python C/C++扩展编译 - 简书 (jianshu.com)

优点:可以在不同系统分别直接生成

构建项目及文件目录,其中build和pyd是通过对setup.py的命令行实现生成的

main.cpp

#include<pybind11/pybind11.h>
#include<pybind11/numpy.h>
#include <iostream>
#include <Eigen/Dense>
#include <Eigen/Core>
using namespace std;

int main()
{
    //建立2行3列矩阵,并为矩阵赋值
    Eigen::Matrix<float, 2, 3> matrix_23;
    matrix_23 << 1, 2, 3, 4, 5, 6;
    cout << matrix_23 << endl;
    //访问矩阵中的元素
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++)
            cout << matrix_23(i, j) << "\t";
        cout << endl;
    }
    //system("pause");
}

PYBIND11_MODULE(eigen_demo, m) {
    m.def("main", &main, "eigen demo");
}

setup.py

from setuptools import Extension
from setuptools import setup

__version__ = '0.0.1'

# 扩展模块
ext_module = Extension(
    # 模块名称
    name='eigen_demo',
    # 源码
    sources=[r'main.cpp'],
    # 包含头文件
    include_dirs=[r'E:\Installed\Anaconda3\include',
                  r'E:\Installed\pybind11-master\include',
                  r'E:\Library\eigen-3.3.4\eigen-3.3.4'],
    # 库目录
    #library_dirs=[],
    # 链接库文件
    language='c++'
)

setup(
    name='eigen_demo',
    version=__version__,
    author_email='[email protected]',
    description='A eigen demo',
    ext_modules=[ext_module],
    install_requires=['numpy']
)

切换到setup.py所在目录(右键目录文件夹——Open In——Terminal),执行以下命令自动生成pyd文件

test.py:导入pyd文件,测试成功

import src.eigen_demo as eigen_demo

eigen_demo.main()

结果:
1 2 3
4 5 6
1    2    3    
4    5    6    

猜你喜欢

转载自blog.csdn.net/m0_67357141/article/details/129389111