Форум сайта python.su
Всем привет!
Есть некая архитектура в которую надо вписать расширяемость с помощью скриптов на питоне. В результате пришлось воспользоваться как методом расширения так и методом внедрения питона. Но это все для общего контекста (проблемы).
Итак есть сишное приложени (вернее С++). В основном потоке приложения создаю еще один для питона, и уже в нем выполняю следующий код:
PyEval_InitThreads();
Py_Initialize(); // <----- здесь поток повисает на ожидании ввода строки из stdin
PyThreadState* mainThreadState = PyEval_SaveThread();
PyGILState_STATE gilState = PyGILState_Ensure();
Py_InitModule ("myModule", myMethods);
char* fileName = (char*)param;
runPyFile (fileName);
PyGILState_Release(gilState);
PyEval_RestoreThread(mainThreadState);
Py_Finalize();
Офлайн
Ввод из stdin скорее всего делает какой-нибудь init<module> из ваших embedded modules.
Стандартный питон такой функциональности не имеет, поверьте.
Вижу еще одну проблему: вы вызывает Py_Initialize/Py_Finalize для каждого запуска, так? Или runPyFile делается один раз за время жизни программы?
Дело в том, что Py_Finalize не сможет корректно выгрузить C Extensions. Просто напросто нет такого API. Есть PEP 3121 http://www.python.org/dev/peps/pep-3121/
на это дело, но его еще не реализовали. Так что как минимум память будет теряться, как максимум (для нетривиальных случаев) - ждите краша.
Офлайн
Спасибо за ответ.
С проблемой разобрался - оказывается был мой косяк. Просто я ожидал ввода в основном потоке, странно почему поток питона повис на этом же вводе. Ну да ладно, в реальных условиях ничего из stdin читать не придется…
А так вообще поток питона запускается один раз… Так что надеюсь описанные выше проблемы меня не каснуться :)
Офлайн
Здравствуйте! У меня похожая задача, прошу совета!
Пытаюсь сделать поддержку приложением питоновских скриптов.
На данный момент связал С++ классы с питоном использую SWIG.
Думаю информация будет полезной для сообщества, напишу подробнее о том как использовал SWIG.
Вот простой пример, исходники на С++:
example.hpp
#pragma once
#include <string>
class A
{
public:
A(void);
std::string getStr(void);
};
#include "example.hpp"
A::A(void) { }
std::string A::getStr(void) {
std::string str("Hello, World!");
return str;
}
%module example
%{
#include "example.hpp"
%}
%include "std_vector.i"
%include "std_string.i"
%include "example.hpp"
:: Запускаю SWIG
"C:\Program Files\SWIG\swigwin-1.3.40\swig.exe" -python -c++ example.i
@echo off
:: Устанавливаю переменные для работы cl.exe
call "C:\Program Files\Microsoft Visual Studio 9.0\VC\vcvarsall.bat"
:: Собираю исходники в DLL, которую сохраняю с расширением *.pyd
"C:\Program Files\Microsoft Visual Studio 9.0\VC\bin\cl.exe" example_wrap.cxx example.cpp -I "C:\Python26\include" /link /OUT:"_example.pyd" /DLL /LIBPATH:"C:\Python26\libs"
:: Удаляю мусор
rm *.exp
rm *.lib
rm *.obj
rm *_wrap.cxx
rm *.pyc
pause
>>> import example
>>> x = example.A()
>>> print x.getStr()
Hello, World!
>>>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <python.h>
#include "example.hpp"
int main(int argc, char *argv[])
{
setlocale(LC_ALL, "Russian");
A *cppx = new A();
Py_Initialize();
PyRun_SimpleString("import example");
// тут нужно что-то сделать чтобы связать cppx и питон
PyRun_SimpleString("print cppx.getStr()");
Py_Finalize();
system("pause");
return EXIT_SUCCESS;
}
Отредактировано (Окт. 11, 2009 14:47:50)
Офлайн
Вот кое-какие продвижения, но с использованием Boost.Python
Вот пример:
#include <stdlib.h>
#include <iostream>
#define BOOST_PYTHON_STATIC_LIB
#include <boost/python.hpp>
using namespace boost::python;
class CppClass {
public:
CppClass()
{
t = 0;
}
int getNum() {
return t;
}
void inc()
{
t++;
}
private:
int t;
};
int main( int argc, char ** argv )
{
setlocale(LC_ALL, "Russian");
try
{
Py_Initialize();
object main_module((handle<>(borrowed(PyImport_AddModule("__main__")))));
object main_namespace = main_module.attr("__dict__");
main_namespace["CppClass"] = class_<CppClass>("CppClass")
.def("getNum",&CppClass::getNum)
.def("inc",&CppClass::inc);
CppClass *cpp = new CppClass();
main_namespace["cpp"] = ptr(cpp);
PyRun_String( "print \"Python: \", cpp.getNum()\n",
Py_file_input, main_namespace.ptr(), main_namespace.ptr());
std::cout << "C++ inc()" << std::endl;
cpp->inc();
PyRun_String( "print \"Python: \", cpp.getNum()\n"
"cpp.inc()\n"
"print \"Python inc()\" \n"
"print \"Python: \", cpp.getNum()\n",
Py_file_input, main_namespace.ptr(), main_namespace.ptr());
std::cout << "C++: " << cpp->getNum() << std::endl;
std::cout << "C++ inc()" << std::endl;
cpp->inc();
PyRun_String( "print \"Python: \", cpp.getNum()\n",
Py_file_input, main_namespace.ptr(), main_namespace.ptr() );
Py_Finalize();
}
catch( error_already_set )
{
PyErr_Print();
}
system("pause");
return EXIT_SUCCESS;
}
Python: 0
C++ inc()
Python: 1
Python inc()
Python: 2
C++: 2
C++ inc()
Python: 3
Для продолжения нажмите любую клавишу . . .
Офлайн
Технически можно и на SWIG, но я бы настоятельно вам не рекомендовал его использовать. Получающиеся объекты по своим характеристикам очень напоминают “морскую свинку”.
Кроме того, в любом случае было бы правильным сделать модуль. Зарегистрируйте его через PyImport_AppendInittab если не хотите выносить в отдельный pyd/so.
Напоследок: пожалуйста, начинайте новые вопросы в новой теме.
Офлайн