Seite 1 von 1

embedding und extending an c++ beispiel

Verfasst: Donnerstag 4. Februar 2010, 20:12
von Francesco
Ich hoffe, ich fange nicht an euch zu nerven.


Ich habe mir überlegt wie ich in einem C++ Python aufrufen kann. Ich habe ein minimales Beispiel, das ich aus verschiednen Sourcen zusammengemergt habe, gemacht (ich weiß dass längerer Code nicht so beliebt ist). Also ich hoffe er ist nicht zu lange.

Das "embedding" funktioniert ja schon mal:

Code: Alles auswählen

//g++ main.cc -o simple `pkg-config gtkmm-2.4 --cflags --libs` -I/usr/include/python2.6  -lpython2.6

#include <iostream>
#include <gtkmm.h>
#include <gtkmm/main.h>
#include <gtkmm/messagedialog.h>

#include "Python.h"

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow();
  virtual ~ExampleWindow();

protected:
  //Signal handlers:
  void on_button_info_clicked();

  //Child widgets:
  Gtk::VButtonBox m_ButtonBox;
  Gtk::Button m_Button_Info;
};

ExampleWindow::ExampleWindow()
: m_Button_Info("Show Info MessageDialog")
{
  set_title("Gtk::MessageDialog example");

  add(m_ButtonBox);

  m_ButtonBox.pack_start(m_Button_Info);
  m_Button_Info.signal_clicked().connect(sigc::mem_fun(*this,
              &ExampleWindow::on_button_info_clicked) );

  show_all_children();
}

ExampleWindow::~ExampleWindow()
{
}

void ExampleWindow::on_button_info_clicked()
{
  
  Py_Initialize();
  PyRun_SimpleString("import sys; import os;");
  PyRun_SimpleString("sys.path.append(os.getcwd())");  
  PyObject* main_module =
     PyImport_AddModule("__main__");

  // Get the main module's dictionary
  // and make a copy of it.
  PyObject* main_dict =
     PyModule_GetDict(main_module);
  PyObject* main_dict_copy =
     PyDict_Copy(main_dict);

  // Execute two different files of
  // Python code in separate environments
  FILE* file_1 = fopen("file1.py", "r");
  PyRun_File(file_1, "file1.py",
             Py_file_input,
             main_dict, main_dict);

  FILE* file_2 = fopen("file2.py", "r");
  PyRun_File(file_2, "file2.py",
             Py_file_input,
             main_dict_copy, main_dict_copy);
  Py_Finalize();
  
  
  Gtk::MessageDialog dialog(*this, "This is an INFO MessageDialog");
  dialog.set_secondary_text(
          "And this is the secondary text that explains things.");

  dialog.run();
}

int main(int argc, char *argv[])
{
  Gtk::Main kit(argc, argv);

  ExampleWindow window;
  //Shows the window and returns when it is closed.
  Gtk::Main::run(window);

  return 0;
}
Was ich jetzt möchte, ist von (momentan ist eine print anweisung in file1.py und file2.py):

Dass ich einem "this" pointer mitgeben kann. im Python script sagt er dann (pseudo code):

Code: Alles auswählen

import examplewindow
examplewindow. m_Button_Info.set_label("neu")

Re: embedding und extending an c++ beispiel

Verfasst: Samstag 6. Februar 2010, 16:48
von Francesco
So, das habe ich hinbekommen. Ein wenig Suchen hilft dann doch weiter. ;)
Mein Code ist wirklich sehr experimentell und daher poste ich den hier jetzt nicht mehr (zu lange wär es auch):
Python Docs und das kde Programm SuperKaramba haben mich weitergebracht, falls es jmd. interessiert.

Entscheidend sind jedenfalls:
Auszüge aus meinem Code:

Code: Alles auswählen


// deklaration

PyObject* py_createBar(PyObject *self, PyObject *args);
PyObject* py_deleteBar(PyObject *self, PyObject *args);

// eine python funktion

PyObject* py_createBar(PyObject *, PyObject *args)
{
    long widget, x, y, w, h;
    char *text;
    if (!PyArg_ParseTuple(args, (char*)"lllll|s", &widget, &x, &y, &w, &h, &text))
        return NULL;

    return (Py_BuildValue((char*)"l", (long)1234));
}

// export tabelle

static PyMethodDef mainwindow_methods[] =
{

  // Bar - bar_python.cpp
  {(char*)"createBar", py_createBar, METH_VARARGS, (char*)"Create new Bar."},
  {(char*)"deleteBar", py_deleteBar, METH_VARARGS, (char*)"Delete Bar."},
    {NULL, NULL, 0 , NULL}
};

// aufruf der python scripts

PyRun_SimpleString((char*)"import sys");
snprintf(pypath, 1023, "sys.path.insert(0, '%s')", theme.path.c_str());
PyRun_SimpleString(pypath);
PyRun_SimpleString((char*)"sys.path.insert(0, '')");
PyImport_AddModule((char*)"mainwindow");
Py_InitModule((char*)"mainwindow", mainwindow_methods);
std::string script = theme.scriptModule;
pName = PyString_FromString(script.erase(script.length() - 3, 3).c_str());
pModule = PyImport_Import(pName);


Re: embedding und extending an c++ beispiel

Verfasst: Montag 8. Februar 2010, 09:03
von Francesco
Ich habe eine Antwort von Krusader Entwickler bekommen. Er sieht es auch so, dass kross (oder SIP) dafür geeigent wären.

Was ich mir nicht vorstellen kann, ist wie man SIP, SWIG oder Boost Python für so ein Plugin System verwenden kann, da es nur eine Binding ("statt" dem Aufruf in puren C(++) darstellen soll).

Also in der Art

import mywrappedcfunction
mywrappedcfunction...

Das heisst, es wird nicht von C(++) heraus aufgerufen, sondern ist in einem völlig eigenen Python Programm untergebracht.

Aber nicht in der Art:

App
C++:
provide modules
call Python script (Pyrun...)

Python:
import AppC++ScriptWrapper
AppC++ScriptWrapper...

Kann mir vielleicht noch jmd. Hinweise geben, ob und wie das mit SWIG, Boost Python, SIP mit embedding/extending in einem funktionieren sollte? Ich blick da nicht ganz durch. Oder habe ich da etwas misverstanden?

Für verschiedene Anwendungen habe ich gesehen.

gnome: PyMethodDef
karamba: PyMethodDef oder kross (Aufrufparamter entscheidet über die Verwendung)
ktorrent: kross

Also in gtk Programme (eigentlich habe ich nur gedit angesehe, das jedoch nicht in C++, sondern in C (gtk) geschrieben ist) habe ich eigentlich nichts anders gesehen als den "herkömmlichen" Weg mit PyMethodDef für diese Art von embedding/extending.

Eine kleine Zusatzfrage noch. Es scheint, als wären die Wrapper in gedit mit einem Tool erzeugt worden, ich habe jedoch noch nicht herausbekomen, wie:

Auszug:
/* -- THIS FILE IS GENERATED - DO NOT EDIT *//* -*- Mode: C; c-basic-offset: 4 -*- */
#line 24 "geditcommands.override"
static PyObject *
_wrap_gedit_commands_load_uri (PyObject *self, PyObject *args, PyObject *kwargs)

Re: embedding und extending an c++ beispiel

Verfasst: Montag 8. Februar 2010, 10:26
von Leonidas
Francesco hat geschrieben:Eine kleine Zusatzfrage noch. Es scheint, als wären die Wrapper in gedit mit einem Tool erzeugt worden, ich habe jedoch noch nicht herausbekomen, wie:

Auszug:
/* -- THIS FILE IS GENERATED - DO NOT EDIT *//* -*- Mode: C; c-basic-offset: 4 -*- */
#line 24 "geditcommands.override"
static PyObject *
_wrap_gedit_commands_load_uri (PyObject *self, PyObject *args, PyObject *kwargs)
Aus welcher Datei hast du das denn?

Re: embedding und extending an c++ beispiel

Verfasst: Montag 8. Februar 2010, 12:50
von Francesco
Aus gedit 2.28.3
(Es gibt anscheinend noch neuere)

gedit-2.28.3/plugin-loaders/python/bindings/geditutils.c
gedit-2.28.3/plugin-loaders/python/bindings/geditcommands.c
gedit-2.28.3/plugin-loaders/python/bindings/gedit.c

Verfasst: Montag 8. Februar 2010, 13:25
von Leonidas
Also Makefile.am sagt dass dort PYGTK_CODEGEN verwendet wird. PYGTK_CODEGEN scheint aus der pygtk-codegen-2.0.in zu kommen (Teil von PyGTK), die wiederrum auf pygobject-codegen-2.0 verweist. Das ist dann wohl das hier.

Verfasst: Montag 8. Februar 2010, 17:23
von Francesco
aha, danke für die Antwort. Jetzt wäre es noch schön, wenn noch jmd. auf meine vorigen "Basisfragen" noch eine Antwort wüsste. :)