【机器学习】C++调用Python3教程

背景

  实际项目中我用的都是C++语言,因为涉及到高性能计算,所以其他听起来牛逼的语言只能用来打下手。现在遇到的一个项目,其深度学习模块是用python语言编写的,现在很多深度学习库都提供了python支持,但是很少有C++支持,就算有C++支持,在windows上编译也有一大堆问题(你说普通人会用Linux?)。幸好python是所谓的胶水语言,能够和C++兼容工作,所以就着手试验C++调用Python。

配置环境

  我使用的配置环境是Windows10, VS2013,anaconda python3.6.4,tensorflow-gpu 1.7,cuda 9.0。
  VS2013项目配置:
  
- 首先是项目属性-C++-include,要包含python.h这个头文件所在的目录,以及numpy/arrayobject.h 头文件所在的目录。后者是使用numpy的条件。
- 项目属性-链接器,附加库目录加入Miniconda3\libs,Miniconda3\Lib,还有numpy的core/lib目录。
- 项目属性-链接器,附加依赖项加入python36_d.lib和npymath.lib。如果没有_d的文件,就拷贝python36.lib并改名为python36_d.lib

debug模式下编译会报错,release不会,这是因为python头文件里面要检查lib文件的调试信息,然而我们只是吧release的lib文件强行当作debug的 lib文件使用。这里要修改头文件:

1 注释掉object.h第56行
//#define Py_TRACE_REFS

2 pyconfig.h 375行
//# define Py_DEBUG

  然后debug就能编译了,但是我们看不到调试信息,只能依赖PyErr_Print()函数输出python错误信息了。

代码

  下面是修改网上C++调用python2.7教程后的代码

#include <iostream>
#include <Python.h>  
#include <numpy/arrayobject.h>
using std::cin;
using std::cout;
using std::endl;
using std::string;
int main(int argc, char *argv[])
{
    Py_Initialize(); //初始化 python  
    import_array();
    if (!Py_IsInitialized())
    {
        cout << "initialized error" << endl;
        return -1;
    }
    PyObject* sys = PyImport_ImportModule("sys");

    std::cout << std::string(Py_GetVersion()) << "\n";

    PyRun_SimpleString("import  sys"); // 执行 python 中的短语句  
    PyRun_SimpleString("print('come in python')");
    PyRun_SimpleString("sys.path.append('./')");
    PyObject *pModule(0), *pDct(0);
    pModule = PyImport_ImportModule("hehe");
    if (!pModule)
    {
        PyErr_Print();
        cout << "can not find pytest.py" << endl;
        return -1;
    }
    else
        cout << "open Module" << endl;
    double *CArrays = new double[3*4*5];
    for (int i = 0; i < 60; ++i)
    {
        CArrays[i] = i + 1;
    }
    npy_intp Dims[3] = { 3, 4,5 }; 
    PyObject *pDict = PyModule_GetDict(pModule);
    PyObject *PyArray = PyArray_SimpleNewFromData(3, Dims, NPY_DOUBLE, CArrays);//构造numpy 数组
    PyObject *ArgArray = PyTuple_New(1);
    PyTuple_SetItem(ArgArray, 0, PyArray);
    PyObject *pFunc = PyDict_GetItemString(pDict, "Show");//获取函数对象
    PyObject_CallObject(pFunc, ArgArray);
    PyErr_Print();
    //Py_DECREF(PyArray);//注意!
    Py_DECREF(ArgArray);
    Py_DECREF(pDict);
    Py_DECREF(sys);
    Py_DECREF(pModule);
    Py_Finalize();
    system("pause");
    return 0;
}
import numpy as np
def Show(Array):
    print("Shape Of Array:", Array.shape)
    print(Array)

  最后输出:
这里写图片描述
  网上其他教程CArray使用的是二维数组,我发现直接使用一维数组是可以的。此外,python2.7版本的教程往往把PyDict_GetItemString写成PyDict_GetAttrString函数,然而python3.6 是不能使用的,返回的总是一个null值,注意这里的区别。
  Py_DECREF(PyArray);和Py_DECREF(ArgArray);只能保留一个,另外一个需要注释掉,因为PyArray和ArgArray被绑定在一起,清除ArgArray连带PyArray也会被清除。如果重复删除PyArray和ArgArray,那么程序执行到Py_Finalize() 就会报错0x0005c。

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值