C++ to numpy and back to C++, tuple PyObject

南笙酒味 提交于 2021-02-10 12:12:33

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!