因为最近项目需要,需要在c++程序中调用python代码进行部分数学预处理,因此在此记录python调用c++的过程,以防自己遗忘,并供大家参考。
测试环境
vs版本:VS2019
Anaconda版本:4.10.3
anaconda版本可以通过如下命令查看:
conda info
使用的python版本为anaconda默认版本:3.6
1.c++环境配置
在调用python之前,我们首先需要在c++项目中配置python依赖库,选择配置的python解释器位于Anaconda下的envs里的torch环境中。
先创建一个c++空项目:
然后在项目属性里分别添加include目录和libs库:
最后添加链接器python37.lib:
至此,c++端环境即配置完毕。
2.python代码编写
接下来,我们需要有一个python代码:
import numpy as np
# import matplotlib.pyplot as plt
class CPID():
def __init__(self):
self.I = 0
self.error_last = 0
def init(self, target, position, KP, KI, KD, KI_limit=None, KI_band=None, Out_limit=None):
self.target = target
self.position = position
self.KP = KP
self.KD = KD
self.KI = KI
self.KI_limit = KI_limit
self.KI_band = KI_band
self.Out_limit = Out_limit
def calculate(self):
error = self.target - self.position
if self.KI_band != None:
if self.I > self.KI_band:
self.I = 0
else:
if self.KI_limit != None:
if self.I > self.KI_limit:
self.I = self.KI_limit
else:
self.I = self.I + self.KI * error
else:
self.I = self.I + self.KI * error
else:
self.I = self.I + self.KI * error
out = self.KP*error + self.I + self.KD*(error-self.error_last)
if self.Out_limit != None:
if out > self.Out_limit:
out = self.Out_limit
self.position = self.position + out
self.error_last = error
# 更新目标
self.target = 500 + np.random.randint(-50, 50)
return self.target, self.position
这是一个简易PID算法,供c++端调用。
3.c++端代码编写
c++端代码如下:
#include <Python.h>
#include <iostream>
//c++调用python
int main()
{
//设置python解释器的路径,避免主机内存在多个python环境导致程序运行错误
Py_SetPythonHome((wchar_t*)L"E:\\anaconda\\envs\\torch");
//进行初始化
Py_Initialize();
//导入python文件路径
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('D://Python_HJ//PID')");
//导入要调用的py文件
PyObject* pModule = PyImport_ImportModule("pid");
//加载文件中的函数名、类名
PyObject* pDict = PyModule_GetDict(pModule);
//根据类名获得该类
PyObject* pClass = PyDict_GetItemString(pDict, "CPID");
//根据函数名获取该函数
/*PyObject* pFunc = PyObject_GetAttrString(pDict, "init");
PyObject* pFunc1 = PyObject_GetAttrString(pDict,"update");*/
//得到类的构造函数
PyObject* pConstruct = PyInstanceMethod_New(pClass);
//类的实例化
PyObject* pInstance = PyObject_CallObject(pConstruct, NULL);
float res1 = 0;
float res2 = 0;
for (int i = 0; i < 100; ++i) {
//调用python对象的方法并赋值
PyObject_CallMethod(pInstance, "init", "iifff", 500, 0, 0.5, 0.01, 0.25);
PyObject* RES = PyObject_CallMethod(pInstance, "calculate", NULL);
//将返回结果转换成C++类型
//PyArg_Parse(RES, "f", &res); 用于处理单数据输出
PyArg_ParseTuple(RES, "ff", &res1, &res2);
std::cout << "target:" << res1 << "\t";
std::cout << "position:" << res2 << std::endl;
}
return 0;
system("pause");
}
运行结果如下:
至此,成功在c++程序中完成对python程序的调用。
这里仍有几个点需要注意:
1.本项目用的是ReleaseX64,若要使用DebugX64版,需要提供python37_d.lib库,若要使用X86版本,则需下载32位的python版本;
2.出现找不到dll文件的情况,需要将python37.dll文件拷贝到c://windows//System32中。