Cython - Implementierung von Callbacks

8

Ich habe mit Cython versucht, mit einer in c ++ geschriebenen Bibliothek zu interagieren. Bis jetzt läuft es ziemlich gut und ich kann die MOST-Funktionen innerhalb der Bibliothek effektiv nutzen. Mein einziges Problem liegt in der Implementierung von Callbacks. Die Bibliothek hat 4 Funktionsdefinitionen, die ungefähr so ​​aussehen:

%Vor%

Um sie zu implementieren, dachte ich, ich würde so etwas mit Cython machen:

%Vor%

Was eigentlich richtig kompiliert, kann ich aber nicht für das Leben von mir denken, wie man das tatsächlich so umsetzt, dass der Callback funktionieren würde. Ich habe zuerst versucht, eine Funktion zu erstellen, die genau so aufgerufen wird, wie Sie es für jede andere Funktion tun würden:

%Vor%

aber das gibt mir den (vorhersehbaren) Fehler:

"Python-Objekt kann nicht in 'Function1'"

konvertiert werden

Also ja, da bin ich. Wenn irgendjemand Erfahrung in der Einrichtung von Callbacks in Cython hat, wäre ich für jede Hilfe sehr dankbar. Danke.

Bearbeiten : Ihrem Rat folgend, habe ich eine Zwischenfunktion mit einem cdef erstellt, die so aussieht:

%Vor%

Das scheint mich erwischt zu haben ... Näher? Einen anderen Fehler jetzt mindestens erhalten:

%Vor%

Nun, soweit ich das beurteilen kann, sind diese Typen identisch, also kann ich nicht herausfinden, was vor sich geht.

Bearbeiten2 : Dieses Problem wurde behoben, indem ein neues Typedef deklariert wurde:

%Vor%

und das als Argument zum Aufruf verwenden, aber anscheinend kam das eigentlich nicht näher, sondern brachte mich nur um eine Nebenspur, da ich beim Versuch, diese Funktion aufzurufen, dasselbe "Kann Python-Objekt nicht konvertieren in 'Function1' "Fehler noch einmal.

Also, ich bin ziemlich genau dort, wo ich angefangen habe. Das Einzige, was ich jetzt tun kann, ist das explizite Umwandeln des Python-Objekts, das als c-Funktion hereinkommt, aber, ehrlich gesagt, ich habe keine Ahnung, wie ich das machen würde.

Bearbeiten Sie das dritte : Okay, nachdem ich deine Antwort analysiert habe, verstehe ich es endlich, und es funktioniert, also hurra und was nicht. Am Ende habe ich eine Funktion wie folgt erstellt:

%Vor%

Nun ist das einzige Problem, dass es const_ushort * Daten nicht in ein Python-Objekt konvertieren kann, aber das ist ein anderes Problem, also denke ich, dass dieses gelöst ist, vielen Dank.

    
Josiah 09.03.2011, 06:09
quelle

2 Antworten

5

Wenn Sie die Bibliothek ändern können, um Folgendes zu definieren:

%Vor%

stattdessen, ich fürchte, du hast kein Glück. Wenn Sie das void* haben, dann definieren Sie eine Funktion, die ein Python-Callable-Objekt mit korrekten Argumenten und SetCallBack mit dieser Funktion und dem aufrufbaren Python aufruft.

Wenn das nicht möglich ist, aber der Callback global ist (so scheint es), können Sie eine globale Variable zum Speichern des Python-Objekts erstellen. Dann erstellen Sie erneut eine Funktion, um das Python-Objekt aufzurufen und zu übergeben to SetCallBack und Ihr PySetCallback würde einfach den globalen Wert festlegen und sicherstellen, dass die richtige Funktion registriert ist.

Wenn der Callback kontextspezifisch ist, Sie aber keine Möglichkeit haben, ihm einen "Benutzerdaten" -Zeiger zu übergeben, habe ich Angst, dass Sie hier kein Glück haben.

Ich kenne Python und C ++, aber nicht Cython, daher weiß ich nicht, ob Sie die Funktion in Cython erstellen können oder ob Sie in C ++ schreiben müssen.

    
Jan Hudec 09.03.2011, 07:10
quelle
8

Ich war kürzlich in der Situation, in der ich auch eine bestehende C ++ - Bibliothek mit Python über Cython verbinden musste, indem ich Events / Callbacks intensiv verwendete. Es war nicht so leicht, Quellen dazu zu finden, und ich möchte das hier zusammenfassen:

Zunächst einmal die Wrapping-C ++ - Callback-Klasse (basierend auf dem 'double ( METHOD) (void )' -Prototyp, könnte aber auch templates sein, da Cython mit Templates umgehen kann):

ALabCallBack.h:

%Vor%

ALabCallBack.cpp:

%Vor%

Wo:

  • 'Callback' :: Die Muster / Konverter-Methode, um eine Python auszulösen (= Methode) Objektmethode aus C typisierten Infos

  • 'method' :: Die effektive Methode, die der Python-Benutzer (= user_data)

  • übergeben hat
  • 'Parameter' :: Der Parameter, der an die 'Methode'

  • übergeben wird

Jetzt müssen wir die .pyx-Datei implementieren ...

Unser Basisprototyp:

%Vor%

Dann stellen wir einen Cython-Wrapper für die C ++ - Klasse zur Verfügung:

%Vor%

Die Muster / Konverter-Methode, die für die Übersetzung eines C-typisierten Prototyps in einen Python-Objekt-Aufruf verwendet wird:

%Vor%

Lassen Sie uns nun diese Features in eine Cython-Klasse einbetten:

%Vor%

Bearbeiten: Bessere Eingabe für die Ausführungsfunktion: def execute = & gt; cpdef double

Das ist es. Nennen Sie es so:

%Vor%

Da Python implizit typisiert ist, können wir auf die Eigenschaften des 'obj' -Objekts zugreifen, das mit der Klasse des als Argument übergebenen Objekts in Beziehung steht, wenn es an der Zeit ist, den Callback auszulösen.

Es kann relativ einfach für die reine C-Implementierung angepasst werden. Bitte sagen Sie mir, ob Sie eine mögliche Verbesserung dafür sehen können (in meinem Fall sind Perfusionen sehr wichtig, da die Ereignisse intensiv abgefeuert werden).

    
Gauthier Boaglio 09.10.2012 22:12
quelle

Tags und Links