[C++-sig] Re: Problem with embedding python with boost.python
Dirk Gerrits
dirk at gerrits.homeip.net
Mon Jul 7 11:39:58 CEST 2003
Pierre Barbier de Reuille wrote:
> I try to embed python in a C++ program. I wrote a module that works if I
> compile it for extending python ... and I wrote a simple interpreter
> that works as an embedded one !
>
> But now I want to extend the embedded interpreter to allow access to the
> C++ classes !
>
> The extension module is called "editor". My problem is that whenever I
> try to import the module in python, the program just abort ... the
> import is done by evaluating 'import edtitor' inside the python
> interpreter ... I show you the interpreter code ! Of course, the module
> is defined using boost.python !
>
> An extra-question is : if I use Py_file_input, I can't retrieve the
> output of the python command, if I use Py_single_input, I can retrieve
> the output, but I can't do any assignment or printing ... how can I have
> both ??? I really begin to think python was not designed to embedded :(
Well this is not really a question of embedding or not. Python's eval,
exec, and execfile statements work in the same way. Anyway, what you
could do is use Py_file_input for all but the last line of code, then
use Py_eval_input for the last line. Or you could let the code store the
result in a variable and read that variable from the main_namespace:
PyObject *obj = PyRun_String("result = 5**2", Py_file_input,
main_namespace.ptr(), main_namespace.ptr());
boost::python::handle<> hres(obj);
boost::python::object res = main_namespace["result"];
> Tthe interpreter class is :
>
> class PythonWnd : public QMainWindow
> {
> Q_OBJECT
>
> public:
> PythonWnd(QWidget * parent = 0, const char * name = 0, WFlags f =
> WType_TopLevel);
> ~PythonWnd();
>
> public slots:
> void evalCommand();
>
> protected:
> void LaunchPython();
> void ClosePython();
> void ExecutePython(const QString command);
> QTextEdit *output;
> QLineEdit *edit;
> QVBox *layout;
> boost::python::object main_module;
> boost::python::dict main_namespace;
>
> };
>
> The initialization function that is :
>
> void PythonWnd::LaunchPython()
> {
> // register the module editor with the interpreter
> if (PyImport_AppendInittab("editor", init_module_editor) == -1)
> {
> cerr << "Error, cannot load editor module !" << endl;
> throw std::runtime_error("Failed to add embedded_hello to the
> interpreter's "
> "builtin modules");
> }
> // Initialize the interpreter
> Py_Initialize();
> // Get the main module ...
> main_module =
> object(boost::python::handle<>(borrowed(PyImport_AddModule("__main__"))));
> main_namespace =
> dict(boost::python::handle<>(borrowed(PyModule_GetDict(main_module.ptr()))));
>
> }
>
> Then the interpretor function (launched each time a line is to be
> evaluated ... it's an iteractive interpretor) is:
>
> void PythonWnd::ExecutePython(const QString command)
> {
> char *cmd;
> cmd = new char[command.length()+1];
> strcpy(cmd, command.latin1());
> stringstream ss;
> try
> {
> PyObject *obj = PyRun_String(cmd, Py_file_input,
> main_namespace.ptr(), main_namespace.ptr());
> boost::python::handle<> hres(obj);
> boost::python::object res(hres);
> //std::string res_cmd = extract<std::string>(res.attr("__repr__")());
> std::string res_cmd = call_method<std::string>(res.ptr(),"__repr__");
> ss << res_cmd;
> }
> catch(error_already_set)
> {
> PyErr_Print();
> ss << "Error, exception thrown ... look at console for details" <<
> endl;
> PyObject *exception, *v, *tb, *hook;
> }
> output->append(ss.str().c_str());
> delete cmd;
> }
>
>
command.latin1() is not null-terminated I think, which would make the
strcpy fail. (Not sure, I don't use Qt.) Wouldn't it be easier and safer
to do:
QString cmd = command + '\0';
...
PyObject *obj = PyRun_String(cmd.latin1(), Py_file_input,
main_namespace.ptr(), main_namespace.ptr());
?
Are you sure the interpreter aborts only when you import your module? If
latin1() does what I think it does then your program could crash on any
piece of Python code.
Regards,
Dirk Gerrits
More information about the Cplusplus-sig
mailing list