Я реализую код Visual C ++ (MS VStudio 2013), который получает изображение с камеры, обрабатывает изображение, отправляет предварительно обработанные данные (массив 2 или более удваивается) на Python через PyObject и возвращает результаты с обработкой кусков обратно из python (кортеж из 3 двойников в py, который становится массивом из 3 двойников в C ++). Я протестировал функцию py как отдельный скрипт. Тем не менее, я продолжаю получать ноль в качестве возврата из PyObject_CallObject (). Python и проект VC ++ находятся в одном каталоге.
Я настроил запись файла журнала в функции py для документирования вызовов из C, поэтому я знаю, что в некоторых случаях вызовы C ++ не достигают функции py, а в других случаях вызывается функция py, но, возможно, возвращенные значения не могут быть обработаны. В частности, я обнаружил, что могу вызывать функцию py (запись положительного журнала), когда кортеж содержит один объект, но я не могу вызвать его (без записей файла журнала), когда кортеж содержит два или более объектов. Кроме того, если функция py не нуждается в аргументах и не должна ничего возвращать, все вызовы успешны.
Я гуглил и прочитал все, что связано с использованием Tuples для связи между 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
* арг)
Вызвать вызываемый объект Python callable_object, с аргументами, данными аргументами кортежа
(акцент мой). Другими словами, второй аргумент PyObject_CallObject
это кортеж аргументов. Ваша функция принимает один аргумент, поэтому длина этого кортежа должна быть 1.
Поскольку вы пытаетесь передать кортеж в качестве этого одного аргумента, вам нужно, чтобы ваш двухэлементный кортеж был первым элементом одноэлементного кортежа, который вы передаете в качестве второго аргумента PyObject_CallObject
,
Другой вариант заключается в использовании PyObject_CallFunction
вместо этого, и пусть он создает кортеж аргумента.