C++调用python代码

C++调用python代码

使用的环境

python3.9.13
opencv
4.6.0
VS2019_community

可能遇到的问题

一、在Release,X64的环境下可以运行,但是在Debug,X64环境下无法运行

在进行了相同的配置后,发现在Debug配置下无法运行,并报错误ModuleNotFoundError: No module named ‘numpy.core._multiarray_umath‘

可能是Numpy版本的原因,也可能是python3.9的Debug不支持到VS2019,但是无从解决

并需要注意到,在配置了numpy的include,lib目录后不要更新numpy==1.xx.x到2.xx版本,2.xx版本的numpy路径有变化,会导致前面的路径失效

二、遇到无法找到python39_d.lib的问题

第一考虑项目配置属性有没有错误

第二考虑是否有安装python的Debug功能

按如下操作查看

在这里插入图片描述

在这里插入图片描述

Modify -> 再点下next来到如下界面,查看红框内两个Debug功能是否有框选

在这里插入图片描述

没框选的话选上,然后install安装,再到python39/libs中查看是否有python39_d.lib,有的话应该就安装成功了

主要流程如下

1. 配置好Python环境和opencv环境

要安装正确版本的python,并配置好系统变量中的Path,如果本机中安装有多个python版本,需将当前项目要使用的python版本系统变量放到其他系统变量的上方,最好置顶,如下所示

在这里插入图片描述

安装好opencv,注意与python的版本支持问题,如opencv-gpu目前只支持python3.8

opencv一样把路径添加到环境变量中的Path

在这里插入图片描述

最好将vc15/bin 也添加到Path中,不然后面可能遇到找不到opencv_worldxxx.dll的问题,选择vc14就添加vc14

2. 项目结构

2.1 在VS中创建一个C++项目

在这里插入图片描述

选择C++控制台应用,项目名称自取,勾选(默认) 解决方案与项目放在同一目录

2.2 导入python项目

将python项目放到C++项目目录下

在这里插入图片描述

右击解决方案->添加->现有项

在这里插入图片描述

选择刚才放到路径下的项目中的python project文件

在这里插入图片描述

2.3 编写C++代码

可以先配置好 3.项目属性配置 再来写C++调用python的代码

在ConsoleApplication1.cpp中编写代码,C++调用python代码样例如下

#include <Python.h>
#include <iostream>
#include <opencv2/core.hpp> 
#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp> 
#include <windows.h>
#include <numpy/ndarrayobject.h>


using namespace cv;
using namespace std;


#define myExport  extern "C" __declspec(dllexport)
#define PI acos(-1)


//导入模型
int import_model(PyObject*& pDict) {
    import_array();                                    //初始化 NumPy 模块
    if (!Py_IsInitialized()) {                         //初始化python接口
        cout << "python init fail" << endl;
        PyErr_Print();
        return -1;
    }
    PyObject* pModule = NULL;                          //初始化变量名为NULL
    PyObject* pFuncFive = NULL;
    PyObject* pReturn = NULL;

    PyRun_SimpleString("import sys");                  //初始化python系统文件路径,保证可以访问到 .py文件
    PyRun_SimpleString("sys.path.append('PyC')");      //PyC是C++所调用的Python文件所在的路径。

    pModule = PyImport_ImportModule("PyC");            //调用python文件名。当前的测试python文件名是 PyC.py
    if (pModule == NULL) {
        cout << "Failed to import Python module" << endl;
        PyErr_Print();
        return -1;
    }
    pDict = PyModule_GetDict(pModule);                                                 //获取模块字典对象
    if (pDict == NULL) {
        cout << "Failed to get module dictionary" << endl;
        PyErr_Print();
        return -1;
    }

    pFuncFive = PyDict_GetItemString(pDict, "load_model");                             //获取模块中的函数
    if (pFuncFive == NULL) {
        cout << "Failed to get module function 'load_model'" << endl;
        PyErr_Print();
        return -1;
    }
    pReturn = PyObject_CallObject(pFuncFive, NULL);                                    //获取函数返回结果
    if (pReturn == NULL) {
        cout << "Failed to get model" << endl;
        PyErr_Print();
        return -1;
    }
    Py_XDECREF(pModule);
    //Py_XDECREF(pFuncFive);
    Py_XDECREF(pReturn);
    return 0;
}


//调用函数获取单张图片中的烟条角度
void get_angle_info(string imgpath, string outpath, int max_angle, PyObject* pDict, char*& nResult) {
    PyObject* pFuncFive = NULL;
    PyObject* pReturn = NULL;

    if (pDict == NULL) {
        cout << "Failed to get module dictionary" << endl;
        PyErr_Print();
        return;
    }
    pFuncFive = PyDict_GetItemString(pDict, "check_angle");                              //获取模块中的函数
    if (pFuncFive == NULL) {
        cout << "Failed to get module function 'check_angle'" << endl;
        PyErr_Print();
        return;
    }
    PyObject* pyStrImgpath = Py_BuildValue("s", imgpath.c_str());
    PyObject* pyStrOutpath = Py_BuildValue("s", outpath.c_str());
    PyObject* pyMaxAngle = Py_BuildValue("i", max_angle);


    PyObject* ArgArray = PyTuple_New(3);                                             //建立参数个数
    PyTuple_SetItem(ArgArray, 0, pyStrImgpath);                                           //第1个参数 
    PyTuple_SetItem(ArgArray, 1, pyStrOutpath);                                           //第2个参数 
    PyTuple_SetItem(ArgArray, 2, pyMaxAngle);                                           //第3个参数 


    pReturn = PyObject_CallObject(pFuncFive, ArgArray);                              //得到函数的返回结果
    if (pReturn == NULL) {
        cout << "Failed to get function return" << endl;
        return;
    }
    
    PyArg_Parse(pReturn, "s", &nResult);

    Py_XDECREF(ArgArray);
    Py_XDECREF(pReturn);
}



myExport void APIGetAngleFromCSharp(char imgpath[], char outpath[], int max_angle, int flag[], char*& nResult, void*& pdict_ptr)
{
    PyObject* pDict = NULL;
    if (flag[0] == 0) {                                                          //回收数据集
        Py_Initialize();                                  //打开python解析器
        import_model(pDict);
        flag[0] = 1;
        pdict_ptr = (void*)pDict;
        return;
    }
    pDict = (PyObject*)pdict_ptr;
    if (pDict == NULL) {
        cout << "Failed to get module dictionary" << endl;
        return;
    }


    if (flag[1] == 1) {
        //Py_XDECREF(pDict);
        Py_Finalize();
        return;
    }
    get_angle_info(imgpath, outpath, max_angle, pDict, nResult);
    flag[2] = 1;

}

3. 项目属性配置

1.第一需要注意的是配置为 Debug 还是 Release ,以及是X64还是X86平台

选哪个的操作一样,但是一定要注意运行时的选项要和配置属性时候选的是一样的

在这里插入图片描述

2.右击项目名称选择属性

在这里插入图片描述

3.此处我们选择Release与X64,并点击VC++目录,添加包含目录以及库目录的路径

在这里插入图片描述

4.其中包含目录添加python与opencv如下路径

在这里插入图片描述

5.库目录

在这里插入图片描述

6.选择C/C++ -> 预处理器 -> 预处理器定义并添加下面字段

NDEBUG
_CONSOLE
_CRT_NONSTDC_NO_DEPRECATE
_CRT_SECURE_NO_WARNINGS

在这里插入图片描述

7.选择链接器 -> 输入 -> 附加依赖项

此处注意

如果是 Debug 配置:此处添加 opencv_world460d.lib ; python39_d.lib

如果是 Release 配置:此处添加 opencv_world460.lib ; python39.lib

opencv和python版本不同会导致后面数字不同,python 3.8版本就是python38.lib,opencv可以到 lib 目录下看看,python在libs下

在这里插入图片描述

在这里插入图片描述

8.点应用或者确定,然后就可以在.cpp文件时写一下demo测试下调用python代码了

  • 23
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值