C++ 到 numpy 并返回到 C++,元组 PyObject
C++ to numpy and back to C++, tuple PyObject
我正在实现一个 Visual C++ 代码 (MS VStudio 2013),它从相机获取图像,处理图像,将预处理数据(数组 2 或更多双精度数)发送到 python 通过PyObject,并从 python 返回经过 numpy 处理的结果(py 中包含 3 个双精度的元组,在 C++ 中变成了包含 3 个双精度的数组)。我将 py 函数作为独立脚本进行了测试。但是,我一直从 PyObject_CallObject() 中得到一个空值作为 return。 python 和 VC++ 项目位于同一目录中。
我在 py 函数中设置了一个日志文件记录来记录来自 C 的调用,所以我知道在某些情况下 C++ 调用不会到达 py 函数,而在其他情况下 py 函数会到达被调用,但也许无法处理 returned 值。具体来说,我发现当元组包含一个对象时我可以调用py函数(正日志记录),但是当元组包含两个或多个对象时我不能调用它(没有日志文件记录)。另外,如果py函数不需要参数,也不需要return任何东西,那么所有的调用都是成功的。
我用谷歌搜索并阅读了与使用元组在 C++ 和 py 之间进行通信有关的所有内容,但仍然无法正常工作。我也阅读了文档和示例,仍然没有运气。
我已将下面的代码精简到最低限度并重现了该问题。下面是我将两个零作为输入传递并期望返回三个零的示例。如果有任何线索,我将不胜感激...
//C++ part
Py_Initialize();
pyName = PyImport_ImportModuleNoBlock(_T("find_center_def"));
if (pyName == NULL) {
return false;
}
pyFunc = PyObject_GetAttrString(pyName, _T("find_center"));
if (pyFunc == NULL) {
return false;
}
Py_DECREF(pyName);
if (PyCallable_Check(pyFunc) == 0) {
return false;
}
PyObject * arg = PyTuple_New(2);
PyObject * datum0 = PyFloat_FromDouble(0.0);
PyObject * datum1 = PyFloat_FromDouble(0.0);
if (PyTuple_SetItem(arg, 0, datum0) != 0) {
return false;
}
if (PyTuple_SetItem(arg, 1, datum1) != 0) {
return false;
}
PyObject * result = PyObject_CallObject(pyFunc, arg);
if (result == NULL) {
return false;
}
OutputDebugString(_T("\nSuccess calling find_center function!"));
#python part, inside of a script called find_center_def.py
def find_center(args):
import numpy
fo=open('foo.txt' ,'w')
fo.write('find_center was called from C++!')
fo.close()
return (0,0,0)
#python output:
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit (AMD64)] on win32
>>> import importlib
>>> test = importlib.import_module("find_center_def")
>>> test.find_center((0,0))
(0, 0, 0)
>>>
您只能向元组添加一个值,因为
PyObject* PyObject_CallObject(PyObject *callable_object, PyObject
*args)
Call a callable Python object callable_object, with arguments given by the tuple args
(强调我的)。换句话说,PyObject_CallObject
的第二个参数是参数的元组。您的函数采用单个参数,因此该元组的长度必须为 1。
由于您试图将元组作为该参数传递,因此您需要将双元素元组作为作为第二个参数传递给 PyObject_CallObject
的单元素元组的第一个元素.
另一种选择是使用 PyObject_CallFunction
,让它构建参数元组。
我正在实现一个 Visual C++ 代码 (MS VStudio 2013),它从相机获取图像,处理图像,将预处理数据(数组 2 或更多双精度数)发送到 python 通过PyObject,并从 python 返回经过 numpy 处理的结果(py 中包含 3 个双精度的元组,在 C++ 中变成了包含 3 个双精度的数组)。我将 py 函数作为独立脚本进行了测试。但是,我一直从 PyObject_CallObject() 中得到一个空值作为 return。 python 和 VC++ 项目位于同一目录中。
我在 py 函数中设置了一个日志文件记录来记录来自 C 的调用,所以我知道在某些情况下 C++ 调用不会到达 py 函数,而在其他情况下 py 函数会到达被调用,但也许无法处理 returned 值。具体来说,我发现当元组包含一个对象时我可以调用py函数(正日志记录),但是当元组包含两个或多个对象时我不能调用它(没有日志文件记录)。另外,如果py函数不需要参数,也不需要return任何东西,那么所有的调用都是成功的。
我用谷歌搜索并阅读了与使用元组在 C++ 和 py 之间进行通信有关的所有内容,但仍然无法正常工作。我也阅读了文档和示例,仍然没有运气。
我已将下面的代码精简到最低限度并重现了该问题。下面是我将两个零作为输入传递并期望返回三个零的示例。如果有任何线索,我将不胜感激...
//C++ part
Py_Initialize();
pyName = PyImport_ImportModuleNoBlock(_T("find_center_def"));
if (pyName == NULL) {
return false;
}
pyFunc = PyObject_GetAttrString(pyName, _T("find_center"));
if (pyFunc == NULL) {
return false;
}
Py_DECREF(pyName);
if (PyCallable_Check(pyFunc) == 0) {
return false;
}
PyObject * arg = PyTuple_New(2);
PyObject * datum0 = PyFloat_FromDouble(0.0);
PyObject * datum1 = PyFloat_FromDouble(0.0);
if (PyTuple_SetItem(arg, 0, datum0) != 0) {
return false;
}
if (PyTuple_SetItem(arg, 1, datum1) != 0) {
return false;
}
PyObject * result = PyObject_CallObject(pyFunc, arg);
if (result == NULL) {
return false;
}
OutputDebugString(_T("\nSuccess calling find_center function!"));
#python part, inside of a script called find_center_def.py
def find_center(args):
import numpy
fo=open('foo.txt' ,'w')
fo.write('find_center was called from C++!')
fo.close()
return (0,0,0)
#python output:
Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit (AMD64)] on win32
>>> import importlib
>>> test = importlib.import_module("find_center_def")
>>> test.find_center((0,0))
(0, 0, 0)
>>>
您只能向元组添加一个值,因为
PyObject* PyObject_CallObject(PyObject *callable_object, PyObject *args) Call a callable Python object callable_object, with arguments given by the tuple args
(强调我的)。换句话说,PyObject_CallObject
的第二个参数是参数的元组。您的函数采用单个参数,因此该元组的长度必须为 1。
由于您试图将元组作为该参数传递,因此您需要将双元素元组作为作为第二个参数传递给 PyObject_CallObject
的单元素元组的第一个元素.
另一种选择是使用 PyObject_CallFunction
,让它构建参数元组。