C++调用python基本数据类型实例--锲而不舍的trying

发布 | 2018-11-01 | 编程学习 | 1503 浏览

无脸男
继翻译完官方文档之后依然没搞明白到底C++是怎么调用python模块的,于是乎,本废柴少女决定再一次勇敢尝试,悲催的是,又要改项目申请书又要改活动文案,是挣扎在时间夹缝中的努力了!!!
可以当废柴,但躺着当一枚废柴就真的是条咸鱼了。orz
ps:本废柴少女不仅废柴,还懒。So直接从我的CSDN账号里原封不动地copy过来了...

okay,to be serious now

----------------------------------------------------------------------------------------------------------这是一条严肃的分割线
本篇blog参考了以下多篇博文,贴出来供大家自行学习
浅析 C++ 调用 Python 模块
C++调用Python实例
C++调用Python浅析
其实很多博客已经讲得蛮具体了,但可能我太小白吧所以摸索了很久才差不多弄出来,我就把步骤写得详细一点供大家参考啦~
Okay下面开始

1.新建项目

打开vs2013,新建一个win32控制台项目,命名为Cpp_calling_pymodel_test,然后新建一个cpp,命名为main(命名都可以自己随便起,这里就以我自己的为栗子吧)。
接下来将Anaconda3文件夹(此处python安装包的解压缩文件夹也同理)下的includelibs两个文件夹拷贝到与Cpp_calling_pymodel_test.sln 的同一目录下。
打开libs 文件夹,拷贝一份其中的python36.lib文件,将其重命名为python36_d.lib(之所以重命名的原因是include目录下的pyconfig.h文件里面的代码在Debug模式下调用的是python36_d.lib文件),具体可见下面的附图啦
工程目录详细

文件夹1:Cpp_calling_pymodel_test:工程同名文件夹,main.cpp在该文件夹下
文件夹2:include :copy from 解压后的Anaconda3文件夹
文件夹3:libs:copy from 解压后的Anaconda3文件夹+1
文件夹4:x64平台文件夹,该文件夹下存放着包含Cpp_calling_pymodel_test.exe的Debug文件夹,具体为什么要换成x64平台在第5小节里会讲到

2.配置属性管理器

C/C++ -->常规 -->附加包含目录 -->添加 F:niukeCpp_calling_pymodel_testinclude

接着
链接器-->常规-->附加库目录-->添加F:niukeCpp_calling_pymodel_testlibs

最后
链接器-->输入-->附加依赖项-->添加python36_d.lib

到这儿,属性配置就okay了~

属性配置
属性配置
属性配置

3.其他

Anaconda3文件夹下的python36.dll文件拷贝到Debug目录下(与Cpp_calling_pymodel_test.exe 同目录)。在该Debug目录下新建一个.txt文件,将其命名为Test_origin.py(具体内容详见后面)
没啥好描述的吧

4.挂代码

首先,main.cpp
接下来我们就要贴代码啦

#include <iostream>
using namespace std;
extern "C"
{
#include "Python.h"
}
//调用输出"Hello Python"函数
void Hello()
{
    Py_Initialize();//调用Py_Initialize()进行初始化
    PyObject * pModule = NULL;
    PyObject * pFunc = NULL;
    pModule = PyImport_ImportModule("Test001");//调用的Python文件名
    pFunc = PyObject_GetAttrString(pModule, "Hello");//调用的函数名
    PyEval_CallObject(pFunc, NULL);//调用函数,NULL表示参数为空
    Py_Finalize();//调用Py_Finalize,和Py_Initialize相对应的.
}
//调用Add函数,传两个int型参数
void Add()
{
    Py_Initialize();
    PyObject * pModule = NULL;
    PyObject * pFunc = NULL;
    pModule = PyImport_ImportModule("Test001");//Test001:Python文件名
    pFunc = PyObject_GetAttrString(pModule, "Add");//Add:Python文件中的函数名
    //创建参数:
    PyObject *pArgs = PyTuple_New(2);//函数调用的参数传递均是以元组的形式打包的,2表示参数个数
    PyTuple_SetItem(pArgs, 0, Py_BuildValue("i", 6));//0--序号,i表示创建int型变量
    PyTuple_SetItem(pArgs, 1, Py_BuildValue("i", 8));//1--序号
    //返回值
    PyObject *pReturn = NULL;
    pReturn = PyEval_CallObject(pFunc, pArgs);//调用函数
    //将返回值转换为int类型
    int result;
    PyArg_Parse(pReturn, "i", &result);//i表示转换成int型变量
    cout << "6 + 8 = " << result << endl;
    Py_Finalize();
}
int main(int argc, char** argv)
{
    cout << "调用Test001.py中的Hello函数..." << endl;
    Hello();
    cout << "\n调用Test001.py中的Add函数..." << endl;
    Add();
    getchar();
    return 0;
}

接着

Test_origin.py

def Hello():
    print("Hello Python")

def Add(a, b):
    return a+b

以上代码参考自C++调用Python实例

按照此方法我们只是实现了基本变量的跨语言调用,更为复杂的图片和模型调用才是我工作的重中之重啦。后续还会持续更新我的学习进展,大家一起day day up~

----------------------------------------------------------------------------------------------------------这是一条严肃的分割线

5.#悲催的后续

即使是现成的代码,自己跑起来可能也有一堆bug,没有bug什么的,永远都是不可能没有bug的,哭!

运行时可能会出现error LNK2019: 无法解析的外部符号
不要慌,可能是平台的问题,比如我就遇到了这个问题,继续哭!我的python是64位的,但我的项目一直是基于32位的platform创建的,所以这里就是改平台的工作啦。
具体可以参考下面两个链接,写得都挺详细的
C++调用python
C++调用python配置及编译出现的问题
我就写下我的操作步骤吧
链接器-->高级-->目标计算机-->MachineX64 (/MACHINE:X64)
目标计算机
接着工程属性改为x64(如下图所示)
工程属性

清理之前的解决方案再次生成就能成功生成.exe 文件啦~
不过不要高兴得太早,因为修改了工程属性,如果你和我一样,一开始使用的都是win32平台,那之前的 Debug目录就得要变成 x64Debug了,oh my dear!
原来的python36.dll文件、Test_origin.py 文件就得拷贝到现在的Debug目录下了。
新的debug文件夹

也许你会觉得到此,终于no problem了吧。
不!
你可能还会遇到下面这个问题,像我一样,哭!

坎坷+1

不要绝望,我只是加了一句代码就成功解决了这个问题。
解决ing

加的就是这么一句代码:

Py_SetPythonHome(L"D:/Anaconda3");

Okay终于完美解决~
调用结果输出

终于啊啊啊啊啊,确认了是条废柴没错了。==

后面继续尝试非基本数据类型的调用,比如图像数据,敬请期待本废柴的next tryout,see you~(Wink~)

标签
没有标签

© 著作权归作者所有

本文由 豆末 创作,采用 知识共享署名4.0 国际许可协议进行许可,本站文章除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。

吐槽一下吧

*选项为必填