深度学习相关的算法,都是使用python语言编写;
应用工程等基本由c++编写;想要将两者很好的结合起来,会缩短开发时间。
编写一个Python脚本:Script1.py
(一开始命名Script.py。这样的命名有坑,会导致后面的程序运行出现问题。后面文件命名要避开这种关键词,然后文件名由Script.py 改成Script1.py)
import tensorflow ##测试这个库的影响
#!/usr/bin/python
# Filename: script.py
class Student:
def SetName(self,name):
self._name = name
def PrintName(self):
print(self._name)
def hello():
print ("Hello World\n")
def world(name):
print ("name")
然后创建一个工程,编写主函数进行调用这个python脚本:main.c++
#include
#include
#include
#include
int main() {
Py_SetPythonHome(L"\\Python366");
# 添加的python的整个完成的环境包的路劲,必须添加。
//使用python之前,要调用Py_Initialize();这个函数进行初始化
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 * pFunc = NULL;
PyObject * pClass = NULL;
PyObject * pInstance = NULL;
//这里是要调用的文件名
pModule = PyImport_ImportModule("Script1");
//这里是要调用的函数名
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);
//测试调用python的类
pClass = PyObject_GetAttrString(pModule, "Student");
if (!pClass) {
printf("Can't find Student class.\n");
return -1;
}
pInstance = PyInstance_New(pClass,Null,Null); // python2的使用语法
pInstance = PyInstanceMethod_New(pClass); //python3的
if (!pInstance) {
printf("Can't create Student instance.\n");
return -1;
}
PyObject_CallMethod(pInstance, "SetName", "s", "my family");
PyObject_CallMethod(pInstance, "PrintName", NULL, NULL);
//调用Py_Finalize,这个根Py_Initialize相对应的。
Py_Finalize();
return 0;
}
然后将系统环境中的python的include、lib和dll进行工程属性的环境配置。即可正常运行
C:\Users\hp\AppData\Local\Programs\Python\Python35\include
C:\Users\hp\AppData\Local\Programs\Python\Python35\libs\python35.lib
Py_SetPythonHome(L"\\Python366");
#include
Py_Initialize();
.... # (所有需要执行的python程序)
Py_Finalize();
分为两种方式
(1)直接Load一个python写好的文件(假设文件名叫pytest.py,在当前目录下)
PyObject *pName, *pMoudule;
PyRun_SimpleString("import sys"); //导入系统模块
PyRun_SimpleString("sys.path.append('./')");
PyRun_SimpleString("print(sys.version)");
pName = PyString_FromString("pytest");
pModule = PyImport_Import(pName); // 或者直接 pModule = PyImport_Import("pytest");
(2)Load一个已经安装好的Python模块 (假设模块名叫numpy)
PyObject* pModule;
pModule = PyImport_Import(PyString_FromString(“numpy”));
//pModule = PyImport_Import(“numpy”);
两种方式
(1)从模块里load一个函数(假设函数名叫func,有一个int型的输入变量,返回一个int型的整数)
PyObject *pfunc, *args, *result;
pfunc = PyObject_GetAttrString(pModule, "func")
args = Py_BuildValue("i", 12345); //设置调用func时的输入变量,这里假设12345
result = PyObject_CallObject(pfunc, args); //执行func(12345),并将结果返回给result
(2)从模块里load一个类,然后调用类内部的函数(假设类名叫Executor,初始化需要当前文件夹下的配置文件config.txt。函数名叫func)
PyObject *pClass, *pDict, *pInStance, *class_args, *result;
pDict = PyModule_GetDict(pModule); //拿到pModule里的所有的类和函数的定义
pClass = PyDict_GetItemString(pDict, "Executor"); //找到名为Executor的类
class_args = Py_BuildValue("(s)", "./config.txt"); //设置类初始化需要的参数
pInstance = PyInstance_New(pClass, class_args, NULL); //初始化Executor,建立实例pInstance
result = PyObject_CallMethod(pInstance, "func", "(i)", 12345); //执行pInstance.func(12345)
因为在Python中,所有的类型都经过了一层封装,导致c++的参数需要做一个类型转换,转换成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");
如果输入参数是另一个python函数的输出结果PyObject* results (o)
PyObject* args = Py_BuildValue("(0)", results);
同c++传递参数到python类似,调用解析函数
单个返回值: PyArg_Parse()
多返回值: PyArg_ParseTuple()
vs配好相关环境,编译运行即可
https://zhuanlan.zhihu.com/p/25888215
int main() {
vector> corr_list;
Py_SetPythonHome(L"Python_env");
//使用python之前,要调用Py_Initialize();这个函数进行初始化
Py_Initialize();
if (Py_IsInitialized())
std::cout << "Init Success" << std::endl;
PyRun_SimpleString("import sys");
PyRun_SimpleString("sys.path.append('./')");
PyRun_SimpleString("print(sys.version)\n");
PyObject * pModule = NULL;
PyObject * pFunc = NULL;
PyObject * pDict = NULL;
PyObject * pReturn = NULL;
//这里是要调用的文件名
pModule = PyImport_ImportModule("Script1");
pFunc = PyObject_GetAttrString(pModule, "szSecTest");
long out_vert[2][3] = { { 2,3,4 },{ 5,6,7 } };
PyObject *PyList = PyList_New(0);//定义该PyList对象为0和PyList_Append有关,相当于定义PyList为[],存放输入数据
PyObject *ArgList = PyTuple_New(1);
for (int i = 0; i <2; i++) {
PyObject *PyList1 = PyList_New(3);
for (int j = 0; j < 3; j++) {
PyList_SetItem(PyList1, j, PyFloat_FromDouble(out_vert[i][j]));
}
PyList_Append(PyList, PyList1);//PyList_Append可以参考Python中,list的append的用处
}
PyTuple_SetItem(ArgList, 0, PyList);//将PyList对象放入PyTuple对象中
pReturn = PyObject_CallObject(pFunc, ArgList);//调用函数,返回一个list
if (PyList_Check(pReturn)) { //检查是否为List对象
corr_list.clear();
vector corr_sub;
int SizeOfList = PyList_Size(pReturn);//List对象的大小,这里SizeOfList = 2
cout <<"output list len: "<< SizeOfList << endl;
PyObject *ListItem=NULL;
PyObject *Item=NULL;
for (int i = 0; i < SizeOfList; i++) {
ListItem = PyList_GetItem(pReturn, i);//获取List对象中的每一个元素
int NumOfItems = PyList_Size(ListItem);//List对象子元素的大小,这里NumOfItems = 2
corr_sub.clear();
for (int j = 0; j < NumOfItems; j++) {
Item = PyList_GetItem(ListItem, j);//遍历List对象中子元素中的每个元素
int result;
PyArg_Parse(Item, "i", &result);//i表示转换成int型变量
corr_sub.push_back(result);
}
corr_list.push_back(corr_sub);
}
Py_DECREF(ListItem); //释放空间
Py_DECREF(Item); //释放空间
}
else { cout << "Not a List" << endl; }
Py_DECREF(pFunc);
Py_Finalize();
cout << "python_env endding......................" << endl;
return 0;
}
Script1.py
def szSecTest(List):
print (List)
IntegerList = []
for i in range(100):
IntegerList.append([1, 2, 3])
return IntegerList