对于纯python程序而言,用c程序来调用是比较适合的,如果python程序中包含了其他第三方库,则调用极可能出错,且不易查明原因。如笔者曾用c程序调用包含tensorflow的python程序,有的可以成功,有的则卡在某条语句,百般尝试也未能实现。

一、纯python程序

以下程序编译环境为VS2013,,所用tensorflow版本为1.4.0 和1.9.0,python版本为3.6.2 。

所做设置也为调用tensorflow所准备,对于普通的python调用而言只多不少:

1、环境配置

需要安装anaconda软件

①将vs工程配置为X64平台

②包含目录 添加路径 D:\anaconda\include

③库目录 添加路径 D:\anaconda\libs

④附加依赖项 添加 python36.lib

2、编写代码如下:

.py文件需和编译生成的.exe文件放在一起

test.py代码

#coding:utf-8

import os

def run(com):

return com

def main():

print(run(("4",3)))

if __name__=='__main__':

main()

c.cpp代码

#include

#include

using namespace std;

int main()

{

//***python调用***//

//初始化python模块

Py_Initialize();

// 检查初始化是否成功

if (!Py_IsInitialized())

{

cout << "初始化失败" << endl;

Py_Finalize();

}

PyObject *pModule;

PyObject*pFunc = NULL;

PyObject*pArg = NULL;

pModule = PyImport_ImportModule("test");//Python文件名

if (!pModule) {

cout << "py文件导入失败" << endl;

Py_Finalize();

}

else{

pFunc = PyObject_GetAttrString(pModule, "run");//Python文件中的函数名

if (!pFunc) {

cout << "函数导入失败" << endl;

Py_Finalize();

}

PyObject* pyParams = Py_BuildValue("(s)","helllo world!");

/*PyObject* pyParams = PyTuple_New(2); //参数传递另外一种形式,待测试

PyObject* pyParams1 = Py_BuildValue("(s)", "5");

PyObject* pyParams2 = Py_BuildValue("(s)", "6");

PyTuple_SetItem(pyParams, 0, pyParams1);

PyTuple_SetItem(pyParams, 1, pyParams2);*/

char * result1;

pArg = PyEval_CallObject(pFunc, pyParams);//调用函数

PyArg_Parse(pArg, "s", &result1);

cout << result1<< endl;

PyObject* pyParams2 = Py_BuildValue("(i)", 123);

int result2;

pArg = PyEval_CallObject(pFunc, pyParams2);//调用函数

PyArg_Parse(pArg, "i", &result2);

cout << result2 << endl;

}

system("pause");

}

执行结果如图

73af1fbf96f147478c6a4c6aa9a026ce.png

以上python程序调用在输入一个参数返回一个参数时成功运行,但是改变c程序,若输入参数变为多个、输出参数也变为多个时运行出错,原因不明,还有待探索。

如果遇到

b2da1de401f54e058cef06b15edaf419.png

可将pyconfig.h文件中的python36_d.lib改为python36.lib即可成功运行。

f1a35d3aab0745e5acb71b5eb36dedd0.png

二、含tensorflow第三方库

在调用含有第三方库的python程序时,首先需要保证在cmd下运行python程序无误。环境配置如上文所述,但是很多时候程序在

pModule = PyImport_ImportModule("test3");//Python文件名

这一行出错,pModule 结果为null,原因通常是import tensorflow as tf这一句未能成功调用,将需调用的python程序中只保留这一句,可轻松验证。

经探索,可在原cpp文件中加入命令行参数即可成功运行。

/**

*Copyright @ 2019 Zhang Peng. All Right Reserved.

*Filename:

*Author: Zhang Peng

*Date:

*Version:

*Description:

**/

#include

#include

using namespace std;

int main()

{

//***python调用***//

//初始化python模块

Py_Initialize();

// 检查初始化是否成功

if (!Py_IsInitialized()) {

printf("py_initialize failed");

}

PyObject *pModule;

PyObject*pFunc = NULL;

PyObject*pArg = NULL;

//main命令行参数

int argc = 1;

wchar_t * argv[] = { L" " };

PySys_SetArgv(argc, argv); //加入argv参数 否则出错

pModule = PyImport_ImportModule("test3");//Python文件名

if (!pModule) {

printf("cannot open module!");

Py_Finalize();

return 0;

}

else

{

pFunc = PyObject_GetAttrString(pModule, "run");//Python文件中的函数名

if (!pFunc) {

printf("cannot open FUNC!");

Py_Finalize();

return 0;

}

else

{

PyObject* pPath = Py_BuildValue("(s)", "7513.jpg");

pArg = PyEval_CallObject(pFunc, pPath);//调用函数

int result;

PyArg_Parse(pArg, "i", &result);

cout << "预测结果: " << result << endl;

}

}

system("pause");

return 0;

}

以上代码中重要的地方就是加入以下几行代码

//main命令行参数

int argc = 1;

wchar_t * argv[] = { L" " };

PySys_SetArgv(argc, argv); //加入argv参数 否则出错

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐