C++数组和python数组相互转换(pybind11 numpy和指针数据转换) tcy

本文详细介绍了如何使用C++模板将指针转换为一维、二维和三维的numpy数组,并提供了针对一维、二维和三维numpy数组的相加函数示例。通过实例演示了如何在C++和Python交互中实现数组运算。

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

1.实例:指针-->numpy

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

#undef max//放在<pybind11/numpy.h>之前(#define NOMINMAX有时不起作用)
#include<pybind11/numpy.h>

namespace py = pybind11;
using namespace py::literals; 
//*指针-->numpy 1D
template<typename T>
py::array_t<T> _ptr_to_arrays_1d(T* data, py::ssize_t col) {
    auto result = py::array_t<T>(col);//申请空间
    py::buffer_info buf = result.request();
    T* ptr = (T*)buf.ptr;

    for (auto i = 0; i < col; i++) 
        ptr[i] = data[i];
    
    return result;
}


//*指针-->numpy 1D
template<typename T>
py::array_t<T> ptr_to_arrays_1d(T* data, py::ssize_t col) {
    py::array_t<double> out = py::array_t<double>(col);
    auto r3 = out.mutable_unchecked<1>();

    for (int i = 0; i < col; i++)
        r3(i) = data[i];

    return out;
}
//*指针-->numpy 2D
template<typename T>
py::array_t<T> _ptr_to_arrays_2d(T* data, py::ssize_t row,py::ssize_t col) {
    auto result = _ptr_to_arrays_1d(data, row * col);
    result.resize({ row,col });//转换为2d矩阵
    return result;
}
//*指针-->numpy 2D
template<typename T>
py::array_t<T> ptr_to_arrays_2d(T* data, py::ssize_t row, py::ssize_t col) {
    py::array_t<T> out = ptr_to_arrays_1d(data,row * col);
    out.resize({ row,col});
   
    return out;
}
//*指针-->numpy 3D
template<typename T>
py::array_t<T> _ptr_to_arrays_3d(T* data, py::ssize_t chunk, py::ssize_t row, py::ssize_t col) {
    auto result = _ptr_to_arrays_1d(data, chunk * row * col);
    result.resize({ chunk,row,col });//转换为2d矩阵
    return result;
} 
//*指针-->numpy 3D
template<typename T>
py::array_t<T> ptr_to_arrays_3d(T* data, py::ssize_t chunk, py::ssize_t row, py::ssize_t col) {
    py::array_t<T> out = ptr_to_arrays_1d(data, chunk * row * col);
    out.resize({ chunk,row,col });

    return out;
}
2.实例:测试-numpy数组相加
//*1d numpy数组相加
py::array_t<double> _add_arrays_1d(py::array_t<double>& arr1, py::array_t<double>& arr2) {
    py::buffer_info buf1 = arr1.request();// 获取arr1, arr2的信息
    py::buffer_info buf2 = arr2.request();

    if (buf1.ndim != 1 || buf2.ndim != 1)
        throw std::runtime_error("Number of dimensions must be one");
    if (buf1.size != buf2.size)
        throw std::runtime_error("Input shape must match");

    auto result = py::array_t<double>(buf1.size);//申请空间
    py::buffer_info buf3 = result.request();

    double* ptr1 = (double*)buf1.ptr;       //获取numpy.ndarray 数据指针
    double* ptr2 = (double*)buf2.ptr;
    double* ptr3 = (double*)buf3.ptr;

    for (int i = 0; i < buf1.shape[0]; i++){//指针访问numpy.ndarray
        ptr3[i] = ptr1[i] + ptr2[i];}

    return result;
}
//*1d numpy数组相加
py::array_t<double> add_arrays_1d(py::array_t<double>& arr1, py::array_t<double>& arr2) {
    auto r1 = arr1.unchecked<1>();
    auto r2 = arr2.unchecked<1>();

    py::array_t<double> out = py::array_t<double>(arr1.size());
    auto r3 = out.mutable_unchecked<1>();

    for (int i = 0; i < arr1.shape()[0]; i++) 
       r3(i) = r1(i) + r2(i);//下标索引访问 numpy.ndarray
        
    return out;
}
//*2d numpy数组相加
py::array_t<double> _add_arrays_2d(py::array_t<double>& arr1, py::array_t<double>& arr2) {
    py::buffer_info buf1 = arr1.request();
    py::buffer_info buf2 = arr2.request();

    if (buf1.ndim != 2 || buf2.ndim != 2)
        throw std::runtime_error("numpy.ndarray dims must be 2!");
    if ((buf1.shape[0] != buf2.shape[0]) || (buf1.shape[1] != buf2.shape[1]))
        throw std::runtime_error("two array shape must be match!");
  
    auto result = py::array_t<double>(buf1.size);//申请内存
    result.resize({ buf1.shape[0],buf1.shape[1] });//转换为2d矩阵
    py::buffer_info buf_result = result.request();

    double* ptr1 = (double*)buf1.ptr;//指针访问读写 numpy.ndarray
    double* ptr2 = (double*)buf2.ptr;
    double* ptr_result = (double*)buf_result.ptr;

    for (int i = 0; i < buf1.shape[0]; i++){
        for (int j = 0; j < buf1.shape[1]; j++){
            auto value1 = ptr1[i*buf1.shape[1] + j];
            auto value2 = ptr2[i*buf2.shape[1] + j];
            ptr_result[i*buf_result.shape[1] + j] = value1 + value2;
        }
    }

    return result;
} 
//*2d numpy数组相加
py::array_t<double> add_arrays_2d_(py::array_t<double>& arr1, py::array_t<double>& arr2) {
    auto r1 = arr1.unchecked<2>();
    auto r2 = arr2.unchecked<2>();

    py::array_t<double> out = py::array_t<double>(arr1.size());
    out.resize({ arr1.shape()[0],arr1.shape()[1] });
    auto r3 = out.mutable_unchecked<2>();

    for (int i = 0; i < arr1.shape()[0]; i++) {
        for (int j = 0; j < arr1.shape()[1]; j++) {
            r3(i,j) = r1(i,j) + r2(i,j);//下标索引访问 numpy.ndarray
        } 
    }
    return out;
}
 
//*2d numpy数组相加
py::array_t<double> add_arrays_2d(py::array_t<double>& arr1, py::array_t<double>& arr2) {
    auto row = arr1.shape()[0], col = arr1.shape()[1];
    py::array_t<double> arr1_ = arr1,arr2_ = arr2;
    arr1_.resize({ row * col });
    arr2_.resize({ row * col });

    auto out = add_arrays_1d(arr1_,arr2_);
    py::array_t<double> out1 = py::array_t<double>(arr1.size());
    out1 = out;
    out1.resize({ row,col });
    
    return out1;
}
//*3d numpy数组相加
py::array_t<double> _add_arrays_3d(py::array_t<double>& arr1, py::array_t<double>& arr2) {
    py::buffer_info buf1 = arr1.request();
    py::buffer_info buf2 = arr2.request();

    if (buf1.ndim != 3 || buf2.ndim != 3)
        throw std::runtime_error("numpy array dim must is 3!");

    for (int i = 0; i < buf1.ndim; i++) {
        if (buf1.shape[i] != buf2.shape[i])
            throw std::runtime_error("inputs shape must match!");
    }

    auto result = py::array_t<double>(buf1.size);
    result.resize({ buf1.shape[0], buf1.shape[1], buf1.shape[2] });
    py::buffer_info buf_result = result.request();

    double* ptr1 = (double*)buf1.ptr;
    double* ptr2 = (double*)buf2.ptr;
    double* ptr_result = (double*)buf_result.ptr;

    auto chunks = buf1.shape[0];
    auto rows = buf1.shape[1];
    auto cols = buf1.shape[2];
    py::ssize_t idx = 0;
    for (int i = 0; i < buf1.shape[0]; i++) {
        for (int j = 0; j < buf1.shape[1]; j++) {
            for (int k = 0; k < buf1.shape[2]; k++) {
                idx = i * rows * cols + j * cols + k;
                ptr_result[idx] = ptr1[idx]+ptr2[idx];
            }
        }
    }
    return result;
} 
//*3d numpy数组相加
py::array_t<double> add_arrays_3d(py::array_t<double>& arr1, py::array_t<double>& arr2) {

    //unchecked<N>          can be non-writeable
    //mutable_unchecked<N>  can be writeable
    auto r1 = arr1.unchecked<3>();
    auto r2 = arr2.unchecked<3>();

    py::array_t<double> out = py::array_t<double>(arr1.size());
    out.resize({ arr1.shape()[0], arr1.shape()[1], arr1.shape()[2] });
    auto r3 = out.mutable_unchecked<3>();

    for (int i = 0; i < arr1.shape()[0]; i++){
        for (int j = 0; j < arr1.shape()[1]; j++){
            for (int k = 0; k < arr1.shape()[2]; k++){
                double value1 = r1(i, j, k);
                double value2 = r2(i, j, k);
                r3(i, j, k) = value1 + value2;//下标索引访问 numpy.ndarray
            }
        }
    }
    return out;
} 
3.c++中测试:

int main() {
    py::scoped_interpreter guard{};//python初始化 
	
	//*测试1D
    double data1[] = {1.1,2.2,3.3,4.4};
    py::array_t<double> _arr1 = _ptr_to_arrays_1d(data1, 4);
    py::array_t<double> _arr2 = _ptr_to_arrays_1d(data1, 4);
    py::array_t<double> arr1 = ptr_to_arrays_1d(data1, 4);
    py::array_t<double> arr2 = ptr_to_arrays_1d(data1, 4);

    py::print("1.1.add_1d=");
    py::print(_add_arrays_1d(_arr1, _arr2));
   
    py::print("1.2.add_1d=");
    py::print(add_arrays_1d(arr1, arr2));

	//*测试2D
    double data2[] = { 1.1,1.2,1.3,2.1,2.2,2.3 };
    _arr1 = _ptr_to_arrays_2d(data2, 2, 3);
    _arr2 = _ptr_to_arrays_2d(data2, 2, 3);
    arr1 = ptr_to_arrays_2d(data2, 2, 3);
    arr2 = ptr_to_arrays_2d(data2, 2, 3);

    py::print("2.1.add_2d=");
    py::print(_add_arrays_2d(_arr1, _arr2));
    
    py::print("2.2.add_2d=");
    py::print(add_arrays_2d(arr1, arr2));

	//*测试3D
    double data3[] = { 
        11.1,11.2,11.3,12.1,12.2,12.3 ,
        21.1,21.2,21.3,22.1,22.2,22.3 };
    _arr1 = _ptr_to_arrays_3d(data3,2, 2, 3);
    _arr2 = _ptr_to_arrays_3d(data3,2, 2, 3);
    arr1 = ptr_to_arrays_3d(data3, 2, 2, 3);
    arr2 = ptr_to_arrays_3d(data3, 2, 2, 3);

    py::print("3.1.add_3d=");
    py::print(_add_arrays_3d(_arr1, _arr2));
    
    py::print("3.4.add_3d=");
    py::print(add_arrays_3d(arr1, arr2));  
}
4.python中测试:

PYBIND11_MODULE(py_numpy, m) {
   m.doc() = "Simple demo using numpy!";

   m.def("_add_arrays_1d", &_add_arrays_1d);
   m.def("_add_arrays_2d", &_add_arrays_2d);
   m.def("_add_arrays_3d", &_add_arrays_3d);
   
   m.def("add_arrays_1d", &add_arrays_1d);
   m.def("add_arrays_2d", &add_arrays_2d);
   m.def("add_arrays_3d", &add_arrays_3d);
}

//python测试代码
import py_numpy as cnp
import numpy as np

data1 = np.array([1, 3, 5, 7, 9])
data2 = np.array([2, 4, 6, 8, 10])
var1 = cnp._add_arrays_1d(data1,data2)
print('var1=', var1)

data1 = np.array(range(0, 16)).reshape([4, 4])
data2 = np.array(range(20, 36)).reshape([4, 4])
var2 = cnp._add_arrays_2d(data1,data2)
print('var2', var2)

data1 = np.array(range(0, 48)).reshape([4, 4, 3])
data2 = np.array(range(50, 50 + 48)).reshape([4, 4, 3])
var3 = cnp.add_arrays_3d(data1,data2)
print('var3', var3)

参考:https ://www.jianshu.com/p/c912a0a59af9

评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值