Callback-Funktionen mit PyCXX und Python

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
svenali
User
Beiträge: 3
Registriert: Freitag 16. Mai 2008, 17:33

Hallo Ihr Lieben,

hoffe nicht das das hier zu Offtopic ist, nur habe ich keine Idee wo ich sonst diese Frage reinposte.

Meine Frage: Wie kann ich eine Python-Funktion aus C++ mit PyCXX heraus aufrufen? Hat da jemand Erfahrung?

Ich selbst bin in der Lage "normale" Wrapper mit PyCXX zu entwickeln. Meine Parameter die von Python kommen, kann ich schön mit dem Py::Tuple auswerten. Alles kein Problem. Nur wie kann ich eben einen Function Pointer unter Python zu meinen C++-Funktionen durchreichen um eben ein Callback zu implementieren? Boost ist mir zu umfangreich. Das muss doch auch mit PyCXX gehen Oder?

Vielen Dank im Voraus. Bis denne.

Liebe Grüße aus dem Norden,
Cu Sven
svenali
User
Beiträge: 3
Registriert: Freitag 16. Mai 2008, 17:33

Hallo Ihr lieben,

Schade, keiner der mir helfen kann. Kennt jemand vielleicht eine Alternative, mit der ich solche Programmieraufgaben bewerkstelligen kann?

LG,
Sven
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Du könntest alternativ natürlich auch die C-API "roh" nutzen, das ist in der Dokumentation beschrieben. Kann dir aber da nicht weiterhelfen, da ich das nicht nutze.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
svenali
User
Beiträge: 3
Registriert: Freitag 16. Mai 2008, 17:33

Hallo Ihr Lieben,

Ich habs, aber eine Verständnisfrage bleibt.

also ich habe eine Lösung gefunden. Leider nicht mit PyCXX aber mit Boost.Python. PyCXX wird das bestimmt auch hinkriegen, nur weiss ich nicht wie.

Zur Lösung:

Eine Wrapper Klasse mit Boost.Python sieht so aus:

Code: Alles auswählen

#include <boost/python/class.hpp>
#include <boost/python/module.hpp>
#include <boost/python/def.hpp>
#include <boost/python/call_method.hpp> 
#include <iostream>
#include <string>

namespace svenali { // Avoid cluttering the global namespace.

  // A friendly class.
  class hello
  {
    public:
      hello(const std::string& country) { this->country = country; }
      std::string greet() const { return "Hello from " + country; }
	  void connect(PyObject* callable) { std::cout << callable << " wird aufgerufen!" << std::endl; mCallBack = callable; } 
	  void throwEvent(std::string s) { boost::python::call_method<void>(mCallBack, s.c_str()); }
    private:
      std::string country;
	  PyObject* mCallBack;
  };

  // A function taking a hello object as an argument.
  std::string invite(const hello& w) {
    return w.greet() + "! Please come soon!";
  }
}

BOOST_PYTHON_MODULE(hello)
{
    using namespace boost::python;
	using namespace svenali;
    class_<hello>("hello", init<std::string>())
        // Add a regular member function.
        .def("greet", &hello::greet)
        // Add invite() as a member of hello!
        .def("invite", invite)
		.def("connect", &hello::connect)
		.def("throwEvent", &hello::throwEvent)
        ;
    
    // Also add invite() as a regular function to the module.
    def("invite", invite);
}
Einfach oder? Jedenfalls viel einfacher als eine PyCXX - Implementation.

Unter Python kann man folgendes machen:

Code: Alles auswählen

#!/usr/bin/env python
# Copyright Stefan Seefeld 2006. Distributed under the Boost
# Software License, Version 1.0. (See accompanying
# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
import hello

class MyClass:
	def __init__(self):
		print "Hello"
		h = hello.hello("Germany")
		print "Class initiate"
		h.connect(self)
		h.throwEvent("cback")

	def cback(self):
		print "Hello World!!!"


h = hello.hello("Germany")
m = MyClass()
Das obige Beispiel zeigt, dass ich meiner C++-Klasse das Python-Object übergebe. Anschließend übergebe ich als String (bei h.throwEvent) die callback-Funktion cback. Es funzt. cback wird von der C++-Instanz aufgerufen.

Eine Frage bleibt für mich jetzt aber dennoch. Kann man hier nicht von Funktionspointern sprechen? Natürlich nicht im Sinne der C-Funktionspointer, aber das Prinzip ist doch das Selbe oder?

Liebe Grüße aus dem Norden,
Euer Sven
Antworten