在c ++中嵌入python时导入tensorflow会返回null

时间:2017-02-12 01:25:52

标签: python c++ tensorflow embedding

我有一个关于将python嵌入到C ++应用程序中的问题。设置如下:我有一个大的C ++应用程序,它生成一些数据(实时渲染图像)并显示它们。我还使用tensorflow在python中训练了一个神经网络,它将接受这些图像。

我的想法是嵌入python并将数据作为numpy数组发送,使用神经网络预测并返回另一个已处理的numpy数组(在C ++中)。我已经在python端进行了一些没有tensorflow的基本测试,以便在c等中嵌入python,这似乎有效。

但是,一旦我将“import tensorflow”放入我要导入的任何python脚本中,我将从c ++部分的PyImport_ImportModule中获取NULL。

e.g。

import numpy as np
def foo(img):
    return np.clip(img * 2.0, 0, 255).astype(np.uint8)

工作正常。但以下情况并非如此:

import numpy as np
import tensorflow as tf #this causes the fail

def foo(img):
    return np.clip(img * 2.0, 0, 255).astype(np.uint8)

在第二种情况下,我仍然从tensorflow中获取stdout中的消息,它已找到cuda等,但模块导入失败。

我的设置是在Windows 10 x64,Anaconda Python 3.5,tensorflow-0.12和CUDA 8.有没有人遇到过类似的问题?我测试过的其他模块(numpy,pil,scipy)似乎装得很好。

如果它看起来无法解决,我会在c ++部分和python之间使用某种类型的IPC。

2 个答案:

答案 0 :(得分:4)

我已经解决了这个问题。我需要使用PySys_SetArgv设置argc和argv。我在导入失败后立即使用PyErr_Occurred()和PyErr_Print()发现了这个问题。

答案 1 :(得分:3)

参考:https://docs.python.org/3.5/extending/embedding.html

的main.cpp

#include <Python.h>
#include <iostream>
#include <QString>
#include <QDir>
#include <cstring>

using namespace std;

int main(int argc, char *argv[])
{
    PyObject *pName, *pModule, *pDict, *pFunc;
    PyObject *pArgs, *pValue;
    int i;

    if (argc < 3) {
        fprintf(stderr,"Usage: call pythonfile funcname [args]\n");
        return 1;
    }

    Py_SetProgramName((wchar_t*)L"test");

    Py_Initialize();

    PySys_SetArgv(argc, (wchar_t**)argv);
    PyRun_SimpleString("import tensorflow as tf\n"
                       "print(tf.__version__)\n");

    PyRun_SimpleString("import cv2\n"
                       "print(cv2.__version__)\n");

    QString qs = QDir::currentPath();
    std::wstring ws = qs.toStdWString();
    PySys_SetPath(ws.data());
    pName = PyUnicode_DecodeFSDefault(argv[1]);
    /* Error checking of pName left out */

    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != NULL) {
        pFunc = PyObject_GetAttrString(pModule, argv[2]);
        /* pFunc is a new reference */

        if (pFunc && PyCallable_Check(pFunc)) {
            pArgs = PyTuple_New(argc - 3);
            for (i = 0; i < argc - 3; ++i) {
                pValue = PyLong_FromLong(atoi(argv[i + 3]));
                if (!pValue) {
                    Py_DECREF(pArgs);
                    Py_DECREF(pModule);
                    fprintf(stderr, "Cannot convert argument\n");
                    return 1;
                }
                /* pValue reference stolen here: */
                PyTuple_SetItem(pArgs, i, pValue);
            }
            pValue = PyObject_CallObject(pFunc, pArgs);
            Py_DECREF(pArgs);
            if (pValue != NULL) {
                printf("Result of call: %ld\n", PyLong_AsLong(pValue));
                Py_DECREF(pValue);
            }
            else {
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
                fprintf(stderr,"Call failed\n");
                return 1;
            }
        }
        else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]);
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", argv[1]);
        return 1;
    }
    Py_Finalize();
    return 0;
}

multiply.py

import tensorflow as tf
import cv2

def multiply(a,b):
    print(tf.__version__) 
    print(cv2.__version__) 
    print("Will compute", a, "times", b)
    c = 0
    for i in range(0, a):
        c = c + b
    return c