前言
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工程属性的包含目录、库目录和附加依赖项中去。如下图:
这里有两点需要注意:
要把模式设置为
Release
而不是Debug
,否则要把python27.lib
改名为python27_d.lib
要根据安装的Python的位数来选择平台为数,比如这里是64位
C++调用Python
在上代码之前还是说一下C++调用Python的一些惯例比较好:
添加头文件
Python.h
,确保文件夹include加入到了包含目录才能调用成功调用的Python代码都需要包含在两行代码中间,即如下形式:
Py_Initialize(); //首。初始化Python解释器
//这里是一堆其他代码
Py_Initialize(); //尾。结束Python的工作。
跟Python相关的东西一般声明为PyObject指针的形式,比如一会见到的如下声明:
PyObject * pModule = NULL; //Python模块
PyObject * pFunc = NULL; //Python函数
PyObject * pArg = NULL; //函数接受的参数
用下面三行代码来完成导入模块、引入函数、构建参数的工作,都是”闻名如见面“类型的函数:
pModule = PyImport_ImportModule("test"); //导入模块
pFunc = PyObject_GetAttrString(pModule, "write_to_xlsx"); //引入操作Excel的函数
pArg = Py_BuildValue("O,O", tuple1, tuple2); //把C++类型转换为Python类型
最后用一句,把参数传给调用函数并实际运行:
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
的内容:
最后的效果
可以看到,传递给Python的参数已经成功的写入Excel并画出了直方图。值得注意的一点是,VS运行程序的时候Excel要关闭,不然会发生写入数据失败。