C++调用Python处理vector

前言

C++和Python都是当前最流行的语言之一,其强大的功能毋庸置疑,它们分别在不同甚至相同的领域发挥着至关重要的作用。C++是底层开发中起着中流砥柱的作用,屹立多年依然势头强劲不露颓势。而Python在最近大热的数据挖掘和人工智能领域独领风骚。而且Python为数极其众多的库支持几乎可以满足各个领域的开发者的需求。

虽然他们都是非常强大的工具,但是在处理特定任务的时候,有时候会存在着方便与否的问题。比如说在算法实现上可能我更喜欢用C++,但是算法最后产生的数据却想交给Python来处理,毕竟Python在数据处理方面用起来更加顺手也更加简单。本文中我们就来看一下如何把C++算法得到的数据vector<float>交给Python然后用Excel画出来。

环境配置

首先需要配置一下环境,我这里用的分别是:

Visual Studio 2017

Anaconda 2 (64位)

正如在Visual Studio中配置其他库(比如OpenCV)一样,我们需要在Visual Studio中添加三个东西

包含目录——include文件夹

库目录——包含.lib文件的文件夹

附加依赖项——.lib文件

按照上面的顺序,我们需要分别将Python安装文件下的inlcude文件夹、libs文件夹和libs文件夹下的python27.lib添加到VS工程属性的包含目录、库目录和附加依赖项中去。如下图:

include和libs

include和libs

这里有两点需要注意:

  • 要把模式设置为Release而不是Debug,否则要把python27.lib改名为python27_d.lib
  • 要根据安装的Python的位数来选择平台为数,比如这里是64位

C++调用Python

在上代码之前还是说一下C++调用Python的一些惯例比较好:

  1. 添加头文件Python.h,确保文件夹include加入到了包含目录才能调用成功
  2. 调用的Python代码都需要包含在两行代码中间,即如下形式:

Py_Initialize(); //首。初始化Python解释器

//这里是一堆其他代码

Py_Initialize(); //尾。结束Python的工作。

  1. 跟Python相关的东西一般声明为PyObject指针的形式,比如一会见到的如下声明:

PyObject * pModule = NULL; //Python模块

PyObject * pFunc = NULL; //Python函数

PyObject * pArg = NULL; //函数接受的参数

  1. 用下面三行代码来完成导入模块、引入函数、构建参数的工作,都是”闻名如见面“类型的函数:

pModule = PyImport_ImportModule("test"); //导入模块

pFunc = PyObject_GetAttrString(pModule, "write_to_xlsx"); //引入操作Excel的函数

pArg = Py_BuildValue("O,O", tuple1, tuple2); //把C++类型转换为Python类型

  1. 最后用一句,把参数传给调用函数并实际运行:

PyEval_CallObject(pFunc, pArg);

实际上到这里就已经把几乎所有能用到的都说个差不多了,在具体说一下C++类型转换为Python类型之前,还是先看一下完整的代码吧。

Show me your code.

vector转为tuple

其他的诸如引入模块、函数之类的是没啥难度的,只需要换个参数而已。这里实际具有技术含量的就是vector对于转化为tuple这一部分了。

其中最主要的一个函数是PyObject *Py_BuildValue(char *format, ...);,此函数作用就是把后面的参数转换成第一个参数format指定的形式,最终返回一个Python对象。官方给出的例子有这些:

但是当我想要把两个vector传给转换成两个tuple的时候,上面给出的N种形式都显得力不从心了。我们希望两个vector传递给Python的时候转换成了两个tuple。但是最后的结果经常是变成了一个个的单个元素,就是不能把这些元素按照原来的vector分成两个元组。经过苦读文档加上实验,format参数是’O’的时候能够满足需求。但是需要我们先把vector转成tuple才能格式化参数。

PyObject* tuple = PyTuple_New(data.size());

先通过PyTuple_New创建一个Python对象,然后利用PyTuple_SET_ITEM把vector的元素一个一个添加到tuple里面去:

PyTuple_SET_ITEM(tuple, i, Py_BuildValue("f", data[i]));

这样,参数就可以经过Py_BuildValue格式化之后传给被调用的函数了。

调用的Python程序

在本文中被调用的Python程序不是我们关注的重点,所以Python代码直接放在这里不做过多的解释。大概意思就是利用Openpyxl,把接收的数据写入Excel,然后画出柱状图。也许以后会放出这方面的内容。现在就只是知道调用的代码长什么样就行。以下是test.py的内容:

最后的效果

include和libs

可以看到,传递给Python的参数已经成功的写入Excel并画出了直方图。值得注意的一点是,VS运行程序的时候Excel要关闭,不然会发生写入数据失败。


最近申请了微信公众号,感兴趣的同学可以左侧扫码关注。

©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页