python使用pybind11调用c++文件

1、安装vs、python
2、安装pybind11:pip install pybind11
3、在一个文件夹中创建sub.cpp、test_sub.py、setup.py文件

(1)sub.cpp用于编写调用的c++代码,例子如下:

#include <pybind11/numpy.h>
#include <pybind11/pybind11.h>

namespace py = pybind11;

int wrap(int x, int dim) {
    int value = x;
    if (value >= dim) {
        value = value - dim;
    }
    if (value < 0) {
        value = value + dim;
    }
    return value;
}

py::array_t<float> gen_normal_map(const py::array_t<float> &range,
                                  const py::array_t<float> &vertex,
                                  const int W,
                                  const int H) {
    pybind11::buffer_info buf1 = range.request();
    pybind11::buffer_info buf2 = vertex.request();

    /*  allocate the buffer */
    py::array_t<float> normal_map_buffer = py::array_t<float>(buf2.size);

    pybind11::buffer_info buf3 = normal_map_buffer.request();

    auto *depth_buffer = (float *)buf1.ptr;
    auto *vertex_map = (float *)buf2.ptr;
    auto *normal_map = (float *)buf3.ptr;

#pragma omp parallel for
    for (int i = 0; i < H * W * 3; ++i) {
        normal_map[i] = 0;
    }

#pragma omp parallel
    {
#pragma omp for nowait collapse(2)
        for (int x = 0; x < W; ++x) {
            for (int y = 0; y < H - 1; ++y) {
                const float &px = vertex_map[y * W * 3 + x * 3];
                const float &py = vertex_map[y * W * 3 + x * 3 + 1];
                const float &pz = vertex_map[y * W * 3 + x * 3 + 2];
                const float &depth = depth_buffer[y * W + x];

                if (depth > 0) {
                    int wrap_x = wrap(x + 1, W);
                    const float &ux = vertex_map[y * W * 3 + wrap_x * 3];
                    const float &uy = vertex_map[y * W * 3 + wrap_x * 3 + 1];
                    const float &uz = vertex_map[y * W * 3 + wrap_x * 3 + 2];
                    const float &u_depth = depth_buffer[y * W + wrap_x];
                    if (u_depth <= 0) {
                        continue;
                    }

                    const float &vx = vertex_map[(y + 1) * W * 3 + x * 3];
                    const float &vy = vertex_map[(y + 1) * W * 3 + x * 3 + 1];
                    const float &vz = vertex_map[(y + 1) * W * 3 + x * 3 + 2];
                    const float &v_depth = depth_buffer[(y + 1) * W + x];
                    if (v_depth <= 0) {
                        continue;
                    }

                    float l = 0.0;
                    float u_normx = ux - px;
                    float u_normy = uy - py;
                    float u_normz = uz - pz;
                    l = sqrt(u_normx * u_normx + u_normy * u_normy +
                             u_normz * u_normz);
                    u_normx /= l;
                    u_normy /= l;
                    u_normz /= l;

                    float v_normx = vx - px;
                    float v_normy = vy - py;
                    float v_normz = vz - pz;
                    l = sqrt(v_normx * v_normx + v_normy * v_normy +
                             v_normz * v_normz);
                    v_normx /= l;
                    v_normy /= l;
                    v_normz /= l;

                    const float crossx = u_normz * v_normy - u_normy * v_normz;
                    const float crossy = u_normx * v_normz - u_normz * v_normx;
                    const float crossz = u_normy * v_normx - u_normx * v_normy;
                    float norm = sqrt(crossx * crossx + crossy * crossy +
                                      crossz * crossz);

#pragma omp critical
                    if (norm > 0) {
                        const float normalx = crossx / norm;
                        const float normaly = crossy / norm;
                        const float normalz = crossz / norm;
                        normal_map[y * W * 3 + x * 3] = normalx;
                        normal_map[y * W * 3 + x * 3 + 1] = normaly;
                        normal_map[y * W * 3 + x * 3 + 2] = normalz;
                    }
                }
            }
        }
    }

    // reshape array to match input shape
    normal_map_buffer.resize({H, W, 3});
    return normal_map_buffer;
}

PYBIND11_MODULE(normal_map, m) {
    m.doc() = "generate normal map using pybind11";
    m.def("gen_normal_map", &gen_normal_map, "generate normal map");
}

#include <pybind11/pybind11.h>表示调用Pybind11的头文件。
PYBIND11_MODULE(normal_map, m)用于定义python模块,normal_map是模块名,m是模块对象。

(2)setup.py用于构建脚本,例子如下:

from glob import glob  
import sys  
  
from pybind11.setup_helpers import Pybind11Extension
from setuptools import setup

# 定义扩展模块,指定前面构建的c++文件
ext_modules = [
    Pybind11Extension(
        "normal_map",  # 模块名
        sorted(glob("*.cpp")),  # c++文件     
        extra_compile_args=["-fopenmp"],
        extra_link_args=["-fopenmp"],
    ),
]

# 定义构建过程
setup(
    ext_modules=ext_modules,
)

(3)将c++文件编译成python模块:
进入文件夹打开终端输入:python setup.py build_ext --inplace

  编译完成后会生成一个.pyd文件

(4)test_sub.py测试:

import normal_map  # 导入模块
	results = gen_normal_map()

最后运行python test_sub.py

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

空谷传声~

您的鼓励是我最大的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值