Уведомления

Группа в Telegram: @pythonsu

#1 Июнь 25, 2012 09:38:55

mrgloom
От:
Зарегистрирован: 2010-07-22
Сообщения: 93
Репутация: +  0  -
Профиль   Отправить e-mail  

вызов питона из с++

Пытаюсь вызывать код питона из с++.

Во-первых в режиме debug не хотят импортироваться файлы завязанные на загрузку .pyd файлов, видимо это связано с тем, что .pyd файлы release?

во вторых странная ошибка с PIL Image

программа не хочет выполнять через PyRun_SimpleString строчку

	if(!PyRun_SimpleString("img = Image.fromstring(\"L\", (size, size), img_str)"))
		LogMsg(_T("erorr\r\n"));
возможно я экранировал символы неправильно? или это каким то образом связано с импортом Image?
хотя эта строчка нормально отрабатывает
if(!PyRun_SimpleString("import Image"))

пробовал сохранять img_str(бинарная строка) в бинарный файл, а потом в консоли его преобразовывать в изображения, изображение получается валидное.


вопрос как мне передать в с++ бинарную строку и распарсить её(хотя бы в raw пиксели).
например так я возвращаю флоат, а как возвратить бинарную строку?

bool CPythonInterface::call_python_func_float(char* module,char* func_name,PyObject *pArgs, float& f)
{
	PyObject *pName, *pModule, *pFunc;
    PyObject *pValue;
    //Py_Initialize();
    pName = PyString_FromString(module);
    /* Error checking of pName left out */
    pModule = PyImport_Import(pName);
    Py_DECREF(pName);
    if (pModule != NULL) 
	{
        pFunc = PyObject_GetAttrString(pModule, func_name);
        /* pFunc is a new reference */
        if (pFunc && PyCallable_Check(pFunc)) 
		{
            pValue = PyObject_CallObject(pFunc, pArgs);
            Py_DECREF(pArgs);
            if (pValue != NULL) 
			{
				
				bool is_float=  PyFloat_Check(pValue);
				f= PyFloat_AsDouble(pValue);
				//PyArg_Parse(pValue, "f", f); //так падает 
                //printf("Result of call: %ld\n", PyInt_AsLong(pValue));
                Py_DECREF(pValue);
            }
            else 
			{
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
                fprintf(stderr,"Call failed\n");
				return false;
            }
        }
        else 
		{
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", func_name);
			return false;
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else 
	{
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", module);
		return false;
    }
    //Py_Finalize();
	return true;
}



___________________________________________________________________________________________
http://www.lfd.uci.edu/~gohlke/pythonlibs/
https://bitbucket.org/pypy/compatibility/wiki/Home

Отредактировано mrgloom (Июнь 25, 2012 09:41:58)

Офлайн

#2 Июнь 25, 2012 10:43:27

mrgloom
От:
Зарегистрирован: 2010-07-22
Сообщения: 93
Репутация: +  0  -
Профиль   Отправить e-mail  

вызов питона из с++

да и еще вопрос проект в котором я вызываю функции из питона можно как то собрать с /MT , похоже работает только с /MD.

точнее с /MT вроде бы работает, но выдает ошибку



___________________________________________________________________________________________
http://www.lfd.uci.edu/~gohlke/pythonlibs/
https://bitbucket.org/pypy/compatibility/wiki/Home

Отредактировано mrgloom (Июнь 25, 2012 10:44:48)

Офлайн

#3 Июнь 26, 2012 22:38:30

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

вызов питона из с++

Про release/debug я вам уже ответил.

PyRun_SimpleString не работает, потому что не находит переменные size и img_str, полагаю.

Бинарные строки: вероятно, вам нужен http://docs.python.org/c-api/buffer.html#the-new-style-py-buffer-struct

Питон собран с /MD, поэтому компиляция его с /MT приводит к ошибкам runtime library. Решение только одно — пересобрать исходники питона и C Extensions с /MT

P.S. Очень порадовали вопросы, было приятно вернуться к давно забытым особенностям python embedding. Там есть еще одна штука: просто так вызывать питон из стороннего потока не выйдет, он крашится (пусть и не с первого раза). Если вам это нужно — расскажу, что делать.

И еще. Попробуйте boost.python — он сократит в разы объем взаимодействующего с питоном кода. Если, конечно, у вас нет жесткого ограничения на используемые библиотеки.



Офлайн

#4 Июнь 27, 2012 12:56:21

mrgloom
От:
Зарегистрирован: 2010-07-22
Сообщения: 93
Репутация: +  0  -
Профиль   Отправить e-mail  

вызов питона из с++

Андрей Светлов
PyRun_SimpleString не работает, потому что не находит переменные size и img_str, полагаю.
нет, они там определены сверху в других PyRun_SimpleString, все таки какая то особенность с PIL Image.
попробую протестировать еще подав заранее заготовленный img_str с диска.

я попробовал сохранять бинарную строку средствами питона на диск, а потом грузить и парсить на с++ и всё работает правильно, за исключением того, что всё гоняется через диск, а это задержка.
но на самом деле мне сохранение через PIL на диск и не надо, мне эту бинарную строку, надо переделать в RAW пиксели(в памяти), ну а потом уже с ними работать сохранить на диск и вывести на форму и т.д.

итак вроде бы даже удалось получить эту бинарную строку,
только всё падает на удалении буфера.
if(PyObject_CheckReadBuffer(pValue))
{
        const char* buf= new char[sz];
	PyObject_AsCharBuffer(pValue, &buf, &sz);
	vector<unsigned char> vec; //вектор на выход чтобы не привязываться к памяти  для питона
	unsigned char* p= (unsigned char*)buf;
	for(int i=0;i<sz;++i)
	{
		vec.push_back(*p);
		++p;
	}
        delete[] buf;//тут всё падает
}

так же пробовал
const char* buf= PyMem_New(char, sz);
...
PyMem_Del((void*)buf);//опять падает
выдаёт
Fatal Python error: bad ID: Allocated using API '

int PyObject_AsCharBuffer(PyObject *obj, const char **buffer, Py_ssize_t *buffer_len)¶
Returns a pointer to a read-only memory location usable as character-based input. The obj argument must support the single-segment character buffer interface. On success, returns 0, sets buffer to the memory location and buffer_len to the buffer length. Returns -1 and sets a TypeError on error.

New in version 1.6.

Changed in version 2.5: This function used an int * type for buffer_len. This might require changes in your code for properly supporting 64-bit systems.

Returns a pointer to a read-only memory location usable as character-based input.
может в этом дело?когда и как память нужно удалять?

This might require changes in your code for properly supporting 64-bit systems.
и какие проблемы могут быть? надо ставить везде Int32?
питон собирается под х64 без проблем? какие еще могут быть проблемы?

Андрей Светлов
Питон собран с /MD, поэтому компиляция его с /MT приводит к ошибкам runtime library. Решение только одно — пересобрать исходники питона и C Extensions с /MT
попробую на досуге, сразу чего то у меня там не завелось.


p.s. Спасибо за компетентные ответы, информацию освещающую процесс python embedding почти нигде не найти.



___________________________________________________________________________________________
http://www.lfd.uci.edu/~gohlke/pythonlibs/
https://bitbucket.org/pypy/compatibility/wiki/Home

Отредактировано mrgloom (Июнь 27, 2012 14:35:28)

Офлайн

#5 Июнь 27, 2012 16:04:51

mrgloom
От:
Зарегистрирован: 2010-07-22
Сообщения: 93
Репутация: +  0  -
Профиль   Отправить e-mail  

вызов питона из с++

заработало, оказывается память сама выделяется и удаляется(правда непонятно как ибо деструктора то нету)

int sz=PyString_Size(pValue);
const char* buf;
PyObject_AsCharBuffer(pValue, &buf, &sz);
vec.assign(buf,buf+sz);



___________________________________________________________________________________________
http://www.lfd.uci.edu/~gohlke/pythonlibs/
https://bitbucket.org/pypy/compatibility/wiki/Home

Отредактировано mrgloom (Июнь 27, 2012 16:06:31)

Офлайн

#6 Июнь 27, 2012 20:17:50

Андрей Светлов
От:
Зарегистрирован: 2007-05-15
Сообщения: 3137
Репутация: +  14  -
Профиль   Адрес электронной почты  

вызов питона из с++

Когда PyObject удаляется — убивается и его буфер.



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version