C++调用C++项目中的Python脚本中的函数和类。,在,工程,python

深度学习相关的算法,都是使用python语言编写;
应用工程等基本由c++编写;想要将两者很好的结合起来,会缩短开发时间。

实际过程中,会把python的脚本编写成类的形式。然后使用C++对python类进行实例化、实例对象的成员函数调用。

1 环境配置

电脑环境:windows10、vs2015、python3.6

【python3.6】

安装anaconda,使用conda创建虚拟环境,并在虚拟环境中配置好自己需要的资源。
找到安装anaconda路径下,创建的虚拟环境的文件夹,我的电脑在默认的路径下【C:\Users\XXX\Anaconda3\envs】。其中 XXX是自己的电脑的名字。
将自己的虚拟环境拷贝,到创建的VS工程下。

【vs2015】

  • 【新建】–>【项目】–>【Visual C++】–>【空项目】–>【修改工程位置和名称】–>【确定】.
  • 将前面说的python的环境拷贝到该工程下。我的虚拟环境命名为 Pyhton_env。
  • 在工程属性中配置。我的工程名为 Project1。
  • C/C++ : $(SolutionDir)Project1\Python_env\include
  • 链接器 : $(SolutionDir)\Project1\Python_env\libs\python36.lib
  • dll :   将 Python_env/python36.dll 拷贝到工程路径下。

2 代码编写

2.1 python脚本的编写

这里举个简单的例子。定义了类,函数。一定要确保,python脚本能够正确的运行通。

class Student():
   def __init__(self):
       print("初始化Student成功============================")

   def SetName(self, name="test1"):
       print("进入Student.SetName成功=======================")

       print("参数:name = " + name)
       self._name = name
       print("成功完成操作:self._name = " + self._name)

   def PrintName(self):
       print("进入Student.PrintName成功=====================")
       print("self._name = " + self._name)

def hello():
   print("进入 hello 函数成功=====================")
   print("Hello World")

def world(name):
   print("进入 world 函数成功=====================")
   print("name")

2.2 C++ 调用 python

【 类的实例化 】

  • 1 打开 python脚本 :

    pModule = PyImport_ImportModule("test1013")
    
  • 2 获取 模块属性字典 : 也就是将python脚本中的定义的类、函数等存入到pDict

    pDict = PyModule_GetDict(pModule);
    
  • 3 根据类名 获取类 :

    pClass = PyDict_GetItemString(pDict, "Student");
    
  • 4 获取 类的构造函数 :

    pConstruct = PyInstanceMethod_New(pClass);
    
  • 5 类的实例

    pInstance = PyObject_CallObject(pConstruct, NULL);
    

【类的调用】

PyObject_CallMethod(pInstance, "SetName", "s", "1111");
#include <Python.h>
#include <iostream>
#include <string>
#include <windows.h> 

int main() {
    
    
	// 添加的python的整个完成的环境包的路劲,必须添加。
	Py_SetPythonHome(L"Python_env");

	// 进行初始化
	Py_Initialize();
	if (Py_IsInitialized())
		std::cout << "Init Success" << std::endl;

	PyRun_SimpleString("import sys");             // 在python初始化之后
	PyRun_SimpleString("sys.path.append('./')");   // ""里面填写的是python的语言
	PyRun_SimpleString("print(sys.version)\n");

	PyObject * pModule = NULL;
	PyObject * pDict = NULL; 
	PyObject * pFunc = NULL; 
	PyObject * pClass = NULL;
	PyObject * pConstruct = NULL;
	PyObject * pInstance = NULL;

	//这里是要调用的文件名
	pModule = PyImport_ImportModule("test1013");

	//加载文件中的函数名、类名
	pDict = PyModule_GetDict(pModule);
	if (!pDict)
	{
    
    
		printf("Cant find dictionary./n");
	}

	// 根据类名获取该类
	pClass = PyDict_GetItemString(pDict, "Student");
	if (!pClass) {
    
    
		printf("Can't find Student class.\n");
		return -1;
	}

	// 得到类的构造函数
	pConstruct = PyInstanceMethod_New(pClass);    //python3的
	if (!pConstruct) {
    
    
		printf("Can't create Student instance.\n");
		return -1;
	}
	// 类的实例化
	pInstance = PyObject_CallObject(pConstruct, NULL);

	PyObject_CallMethod(pInstance, "SetName", "s", "1111");
	PyObject_CallMethod(pInstance, "PrintName", NULL, NULL);

	{
    
    
		//调用python脚本中的函数 并执行
		pFunc = PyObject_GetAttrString(pModule, "hello");
		//调用函数
		PyEval_CallObject(pFunc, NULL);
		Py_DECREF(pFunc);

		pFunc = PyObject_GetAttrString(pModule, "world");
		PyObject_CallFunction(pFunc, "s", "zhengji");
		Py_DECREF(pFunc);
	}

	//调用Py_Finalize,这个根Py_Initialize相对应的。
	Py_Finalize();

	return 0;

}

运行结果为:
在这里插入图片描述

2.3 传参的方式

从 C++ 向 python 传参之前,需要做类型转换。转为 PyObject* 才能传入 python。

例如:
C++的 int 是一个整数,该值占用 8bytes(64位)的存储空间,而一个 python 的 int 实际是一个 PyObject* 指向 24bytes。
前 8个bytes是整数,代表引用次数;中间 8bytes是指向 int 类型定义的指针,最后 8bytes是才是这个 int 的值。
所以 C++ 和 Python 之间参数互相传递都需要 Python提供的 api。

假设函数的输入变量有三个,分别为 一个整数(i),一个浮点数(f),一个字符串(s)

PyObject* args = PyTuple_New(3);
PyObject* arg1 = Py_BuildValue("i",100);  //整数参数
PyObject* arg2 = Py_BuildValue("f", 3.14);  //浮点数参数
PyObject* arg3 = Py_BuildValue("s", "hellow"); //字符串参数

PyTuple_SetItem(args, 0, arg1);
PyTuple_SetItem(args, 0, arg2);
PyTuple_SetItem(args, 0, arg3);

// 以上的函数可简化为
// PyObject* args = Py_BuildValue("ifs", 100, 3.14, "hellow");

猜你喜欢

转载自blog.csdn.net/qq_45662588/article/details/120545455
今日推荐