c++调用python和numpy混合编程


在现代软件开发中,跨语言编程和混合编程的需求日益增长。C++作为一种高效、强大的编程语言,广泛应用于底层开发、游戏引擎、高性能计算等领域。而Python则因其简洁的语法、丰富的库和易于学习的特性,在数据科学、机器学习、Web开发等领域占据重要地位。NumPy是Python中一个用于数值计算的库,提供了大量的数学函数以及多维数组和矩阵运算的功能,是数据科学领域的核心工具之一。

为了满足在C++项目中利用Python和NumPy能力的需求,开发者们可以采用混合编程的方式,即让C++代码调用Python脚本,并在Python脚本中利用NumPy库进行数值计算。这种编程方式结合了C++和Python的优势,使得开发者能够在一个项目中同时利用C++的高性能和Python的丰富功能。

实现方式:

使用Python/C API:Python提供了一套C API,允许C/C++代码直接调用Python代码。开发者可以通过这些API来初始化Python解释器、加载Python模块、调用Python函数等。但是,这种方式需要开发者对Python的内部机制有较深的了解,编程难度较大。

在C++调用Python并使用NumPy的场景中,开发者通常需要在Python脚本中定义好需要使用的NumPy函数,并在C++代码中通过API或第三方库来加载和执行这些脚本。这样,C++代码就可以通过Python脚本间接地利用NumPy库的功能了。

应用场景:

高性能计算:在某些高性能计算场景中,C++代码负责处理大量数据,而Python和NumPy则用于进行复杂的数学运算或数据分析。通过混合编程,可以将这两者的优势结合起来,提高整体计算效率。
机器学习:在机器学习中,Python和NumPy是常用的工具。但是,在某些情况下,需要使用C++进行底层优化或与其他系统进行交互。通过混合编程,可以在保持Python和NumPy便利性的同时,利用C++的优势来提升性能或实现特定的功能。
数据可视化:在数据可视化领域,Python有许多优秀的库(如Matplotlib)可以用于生成高质量的图表。而C++则常用于实时渲染和交互式界面开发。通过混合编程,可以将C++的界面与Python的数据可视化功能结合起来,为用户提供更好的体验。

1. cmake 配置

# main CMakeLists.txt
cmake_minimum_required(VERSION 3.20 FATAL_ERROR)

project(TEST)
# set(CMAKE_BUILD_TYPE "Debug") # 用于debug
set(CMAKE_CXX_STANDARD 14)

set(MPI_C_COMPILER_INCLUDE_DIRS /opt/hpcx/ompi/include CACHE PATH "")

add_subdirectory(src)

add_executable(TEST main.cpp)

target_link_libraries(TEST mycpp pthread stdc++fs)
target_include_directories(TEST PUBLIC ${MYCPP_INCLUDE_DIR})
target_link_directories(TEST PUBLIC ${VTK_LIBRARY_DIRS} ${OPENCV_LIBRARY_DIRS} ${PCLFUNCTION_DIR} ${PCL_INCLUDE_DIRS})
# sub CMakeLists.txt
project(TEST)

set(MYCPP_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE PATH "")
message(STATUS "MYCPP_INCLUDE_DIR : ${MYCPP_INCLUDE_DIR }")
find_package( OpenCV REQUIRED )
find_package(VTK REQUIRED)
find_package(PCL REQUIRED)

# set(Python3_ROOT_DIR "/opt/conda/envs/xxx/bin/python")
find_package(Python3 3.10 COMPONENTS Interpreter Development NumPy REQUIRED)

set(Python3_EXECUTABLE Python3::Interpreter)

message(STATUS "Python3_ROOT_DIR: ${Python3_ROOT_DIR}")
message(STATUS "Python3_INCLUDE_DIRS: ${Python3_INCLUDE_DIRS}")
message(STATUS "Python3_LIBRARIES: ${Python3_LIBRARIES}")
message(STATUS "Python3_LIBRARY_DIRS: ${Python3_LIBRARY_DIRS}")
message(STATUS "Python3_NumPy_FOUND: ${Python3_NumPy_FOUND}")
message(STATUS "Python3_NumPy_INCLUDE_DIRS: ${Python3_NumPy_INCLUDE_DIRS}")
message(STATUS "Python3_NumPy_VERSION: ${Python3_NumPy_VERSION}")


add_library(mycpp SHARED mycpp.cpp mycpp.h)
target_link_libraries(mycpp ${OpenCV_LIBS} pclFunction pthread ${Python3_LIBRARIES} Python3::NumPy) # ${PYTHON_LIBRARIES} ${Boost_LIBRARIES}
target_include_directories(mycpp PUBLIC ${PCL_INCLUDE_DIRS} ${PCLFUNCTION_DIR} ${Python3_INCLUDE_DIRS})

2. python脚本

python接收c++传入,并返回计算后的结果给c

  • 11
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++调用 Python 进行矩阵运算,可以使用 Python 的 C API 或者使用第三方库。这里介绍使用第三方库 Boost.Python 实现 C++ 调用 Python 进行矩阵运算的方法。 首先,需要安装 Boost.PythonNumPy 库。Boost.Python 是一个 C++ 库,用于将 C++ 代码与 Python 解释器集成在一起。NumPy 是一个 Python 库,用于高效地计算多维数组和矩阵。 假设我们已经安装好了 Boost.PythonNumPy 库,并且已经编写好了一个 Python 脚本 `matrix.py`,用于实现矩阵计算。该脚本中包含了一个名为 `matrix_multiply` 的函数,用于计算两个矩阵的乘积。可以使用以下代码将该函数导出到 C++ 中: ```python #include <boost/python.hpp> #include <numpy/arrayobject.h> using namespace boost::python; // 导出函数 object matrix_multiply(object A, object B) { // 将 Python 对象转换为 NumPy 数组 PyArrayObject *array_A = reinterpret_cast<PyArrayObject*>(A.ptr()); PyArrayObject *array_B = reinterpret_cast<PyArrayObject*>(B.ptr()); // 获取数组的维度和元素类型 int ndim_A = PyArray_NDIM(array_A); int ndim_B = PyArray_NDIM(array_B); int *shape_A = PyArray_SHAPE(array_A); int *shape_B = PyArray_SHAPE(array_B); int dtype_A = PyArray_TYPE(array_A); int dtype_B = PyArray_TYPE(array_B); // 检查数组的维度和元素类型是否正确 if (ndim_A != 2 || ndim_B != 2 || shape_A[1] != shape_B[0] || dtype_A != NPY_DOUBLE || dtype_B != NPY_DOUBLE) { PyErr_SetString(PyExc_ValueError, "Invalid input arguments"); throw_error_already_set(); } // 创建输出数组 npy_intp shape_C[] = {shape_A[0], shape_B[1]}; PyArrayObject *array_C = reinterpret_cast<PyArrayObject*>(PyArray_SimpleNew(2, shape_C, NPY_DOUBLE)); // 计算矩阵乘积 double *data_A = reinterpret_cast<double*>(PyArray_DATA(array_A)); double *data_B = reinterpret_cast<double*>(PyArray_DATA(array_B)); double *data_C = reinterpret_cast<double*>(PyArray_DATA(array_C)); for (int i = 0; i < shape_A[0]; i++) { for (int j = 0; j < shape_B[1]; j++) { double sum = 0.0; for (int k = 0; k < shape_A[1]; k++) { sum += data_A[i * shape_A[1] + k] * data_B[k * shape_B[1] + j]; } data_C[i * shape_B[1] + j] = sum; } } // 将输出数组转换为 Python 对象并返回 object result = object(handle<>(array_C)); Py_INCREF(array_C); return result; } // 导出模块 BOOST_PYTHON_MODULE(matrix) { import_array(); def("matrix_multiply", matrix_multiply); } ``` 在上面的代码中,我们首先包含了 Boost.PythonNumPy 库的头文件。然后,定义了一个名为 `matrix_multiply` 的函数,用于计算两个矩阵的乘积。该函数的输入参数是两个 Python 对象 `A` 和 `B`,分别代表两个矩阵。在函数中,我们将 Python 对象转换为 NumPy 数组,并检查数组的维度和元素类型是否正确。然后,创建输出数组 `C`,并使用三重循环计算矩阵乘积。最后,将输出数组转换为 Python 对象并返回。 在定义完函数后,我们使用 Boost.Python 导出该函数,并将其编译为动态链接库。在 C++ 中,可以使用以下代码调用该函数: ```cpp #include <iostream> #include <boost/python.hpp> using namespace std; using namespace boost::python; int main() { // 初始化 Python 解释器 Py_Initialize(); import_array(); try { // 导入 Python 模块 object module = import("matrix"); // 创建输入矩阵 npy_intp shape_A[] = {2, 3}; double data_A[] = {1, 2, 3, 4, 5, 6}; object A = object(handle<>(PyArray_SimpleNewFromData(2, shape_A, NPY_DOUBLE, data_A))); npy_intp shape_B[] = {3, 2}; double data_B[] = {7, 8, 9, 10, 11, 12}; object B = object(handle<>(PyArray_SimpleNewFromData(2, shape_B, NPY_DOUBLE, data_B))); // 调用 Python 函数 object C = module.attr("matrix_multiply")(A, B); // 打印输出矩阵 PyArrayObject *array_C = reinterpret_cast<PyArrayObject*>(C.ptr()); double *data_C = reinterpret_cast<double*>(PyArray_DATA(array_C)); int *shape_C = PyArray_SHAPE(array_C); for (int i = 0; i < shape_C[0]; i++) { for (int j = 0; j < shape_C[1]; j++) { cout << data_C[i * shape_C[1] + j] << " "; } cout << endl; } } catch (error_already_set) { PyErr_Print(); } // 关闭 Python 解释器 Py_Finalize(); return 0; } ``` 在上面的代码中,我们首先初始化 Python 解释器,并导入 Boost.PythonNumPy 库。然后,使用 Boost.Python 导入 Python 模块 `matrix`。接着,创建两个输入矩阵 `A` 和 `B`,并将其作为参数调用 Python 函数 `matrix_multiply`。最后,将输出矩阵 `C` 打印出来,以验证计算结果是否正确。 需要注意的是,使用 Boost.Python 调用 Python 函数时,需要在程序开头和结尾分别调用 `Py_Initialize()` 和 `Py_Finalize()` 函数来初始化和关闭 Python 解释器。在 C++ 中,可以使用 Boost.Python 提供的 `object` 类型来表示 Python 对象,使用 `attr` 函数来调用 Python 对象的属性或方法。在将 Python 对象转换为 NumPy 数组时,需要使用 `reinterpret_cast` 函数进行类型转换。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值