问题
I am implementing a Visual C++ code (MS VStudio 2013) that acquires an image from a camera, processes the image, sends pre-processed data (an array 2 or more doubles) to python through a PyObject, and gets numpy-processed results back from python (a tuple of 3 doubles in py, which is becomes an array of 3 doubles in C++). I tested the py function as a standalone script. However, I keep getting a null as a return from PyObject_CallObject(). python and the VC++ project reside in the same directory.
I have set up a log file record in the py function to document the calls from C, so I know that in some cases the C++ calls do not reach the py function, and in other cases the py function does get called, but, perhaps, the returned values cannot be processed. Specifically, I found that I can call the py function (positive log record) when the tuple contains one object, but I cannot call it (no log file records) when the tuple contains two or more objects. In addition, if the py function needs no arguments, and does not need to return anything, all calls are successful.
I have googled and read everything having to do with using Tuples to communicate between C++ and py, but still did not make it work. I have also read the documentation and the examples, still no luck.
I have stripped the code to a bare minimum below and reproduced the problem. Below is an example when I pass two zeros as input, and expect to get three zeros back. I would be very grateful for any leads on this...
//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)
>>>
回答1:
You're only able to add a single value to your tuple because
PyObject* PyObject_CallObject(PyObject *callable_object, PyObject *args) Call a callable Python object callable_object, with arguments given by the tuple args
(emphasis mine). In other words, the second argument to PyObject_CallObject
is a tuple of the arguments. Your function takes a single argument, so the length of that tuple has to be 1.
Since you're trying to pass a tuple as that one argument, you need your two-element tuple to be the first element of a single-element tuple that you pass as the second argument to PyObject_CallObject
.
Another option is to use PyObject_CallFunction
instead, and let it build the argument tuple.
来源:https://stackoverflow.com/questions/29804623/c-to-numpy-and-back-to-c-tuple-pyobject