Callback Funktion deklarieren und anwenden ?

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
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

Hi,
im Zusammenhang mit der COM Schnittstelle der Telefonsoftware Phoner, habe ich folgende
Antwort bekommen:

Code: Alles auswählen

Versuche dir einfach die OnChangeState-Funktion als Callback Function vorzustellen. 
So nach dem Motto: "Wenn du mir was zu sagen hast, dann rufe doch die Funktion, welche ich dir hier übergebe". 
Natürlich muss die Funktionsdeklaration übereinstimmen. 
Jetzt bin ich ich noch verwirrter als vorher. Ich habe noch nie mit Callbackfunktionen zu tun gehabt
und weiss nicht, wie ich die in Python deklariere und anwende.
Die oben zitierte 'OnChangeState(CallID)' Funktion ist eine Event-Funktion des COM-Servers der Software.
Den kann ich zwar ansprechen, aber die Eventfunktion will mir ihre Ergebnisse über Phoner.CPhoner.OnChangeState(CallID)
nicht übermitteln. Wie ginge der Aufruf mittels eines Callbacks ?

Habe im Wiki über Callback Funktionen nachgelesen, aber alles was ich verstanden habe ist, daß die Callback Funktion einer anderen Funktion als Parameter übergeben wird. Das hieße in meinem Fall, daß ich eine eigene Funktion 'OnChangState()' schreibe und ihr als Parameter 'Phoner.CPhoner.OnChangeState' übergebe ? Das führt aber zu einem Attribut Error.

Code: Alles auswählen

def OnChangeState(CallID):
    StateString = ""
    CallerIDString = ""
    CalledIDString = ""

    phon.GetState(CallID, StateString)
    phon.GetCallerID(CallID, CallerIDString)
    phon.GetCalledID(CallID, CalledIDString)
    return CallID

phon = win32com.client.Dispatch("Phoner.CPhoner")
print OnChangeState(phon.OnChangeState)

Code: Alles auswählen

File "C:\Programme\Python24\Lib\site-packages\win32com\client\dynamic.py", line 489, in __getattr__
raise AttributeError, "%s.%s" % (self._username_, attr)
AttributeError: Phoner.CPhoner.OnChangeState
Gruss, Seven
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Probiers mal andersrum, also dem Attribut Deine Callback-Funktion zuzuweisen. (nur so nebenbei: callback macht genau das was drinsteht: es ist ein Rückruf. Irgendein Objekt/eine Funktion meldet sich bei Dir um Dir irgendwas mitzuteilen per Rückruf, nachdem Du sie zuerst angerufen hast)

Beispiel in Python:

Code: Alles auswählen

def meinCallback(*args):
    print "Im Callback:", args

class MeineKlasse(object):

    def __init__(self,callback):
        self._cb = callback # Speichern der Callback-Funktion entspricht der Attributzuweisung.

    def machWas(self):
        print "Ich mache was."
        for i in range(10):
            print "Mach was ist bei Schritt:", i
            self._cb(i) # Signalisiere Callback wo man gerade ist.
            time.sleep(1)

x = MeineKlasse(meinCallback)
x.machWas()
Ausführen und genießen.

Das entspräche ungefähr dem was Du machen würdest wenn Du dem Attribut OnStateChange die Callback-Funktion die Du haben willst zuweisen würdest.

--- Heiko.
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

Das Beispiel ist gut, aber ich bekomme immer noch keinen Bezug zu
meiner Konstellation. Was entspricht dem Attribut 'OnChangeState' ? 'X' oder oder 'MeineKlasse' ? Und wie bekomme ich den Bezug zum COM Server Objekt ? Wenn ich mit 'Phoner.CPhoner.OnChangeState' dem Objekt versuche was zuzuweisen, bekomme ich die Meldung, dass dem Objekt nichts zugewiesen werden kann und wenn ich 'Phoner.CPhoner.OnChangeState' als Parameter übergebe, bekomme ich einen Attribut Error ?? Ich ahne zwar jetzt, worauf es hinausläuft (Daten durch die Hintertür auslesen), aber es klappt leider noch nicht :cry:
Gruß und Danke ! Seven
modelnine
User
Beiträge: 670
Registriert: Sonntag 15. Januar 2006, 18:42
Wohnort: Celle
Kontaktdaten:

Probier:

Code: Alles auswählen

phon.OnStateChange = OnStateChange
--- Heiko.
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

modelnine hat geschrieben:Probier:

Code: Alles auswählen

phon.OnStateChange = OnStateChange
--- Heiko.
Bringt wieder denselben Fehler:

Code: Alles auswählen

AttributeError: Property 'Phoner.CPhoner.OnChangeState' can not be set.
Gruss, Seven
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

Habe in diesem Zusammenhang von einer win32com.client-Funktion getevents() gehört, aber keine Infos darüber gefunden (der Link war nicht mehr zugänglich). Gibt es die und weiss einer, was die macht ?

Gruss, Seven
Buell
User
Beiträge: 90
Registriert: Samstag 29. Oktober 2005, 14:17

win32com.client.getevents() erzeugt einen EventListener.

Bsp:

Code: Alles auswählen

class ContextEvents(win32com.client.getevents("SAPI.SpSharedRecoContext")):
    """Called when a word/phrase is successfully recognized  -
        ie it is found in a currently open grammar with a sufficiently high
        confidence"""
    def OnRecognition(self, StreamNumber, StreamPosition, RecognitionType, Result):
        newResult = win32com.client.Dispatch(Result)
        print "You said: " + str(newResult.PhraseInfo.GetText())
Wenn die COM-Schnittstelle Events erzeugt, kannst du sie damit "abhören". Dazu ist jedoch erforderlich, dass das Modul in dem der Listener läuft in einer schleife hängt, also mindestens so lange wartet bis ein Event kommt. Es empfiehlt sich deswegen das Listening in einen Thread zu packen, aber niemals das gesamte Modul, denn dann geht es nicht mehr.
Ob dir das allerdings bei deinem Problem weiterhilft...
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

Danke, ich werde es zumindest versuchen. Vieleicht läßt sich damit dem OnChangeState Event auf die Schliche kommen ? Seven
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

Also, um erstmal zu sehen, was getevents() überhaut macht, habe ich ein

Code: Alles auswählen

help(win32com.client.getevents("Phoner.CPhoner"))
eingegeben und das da bekommen:

Code: Alles auswählen

Help on class ICPhonerEvents in module win32com.gen_py.98898140-96E2-11D3-A1D0-444553540000x0x1x0:

class ICPhonerEvents
 |  Ereignis-Schnittstelle für CPhoner-Objekt
 |  
 |  Methods defined here:
 |  
 |  __del__(self)
 |  
 |  __init__(self, oobj=None)
 |  
 |  close(self)
 |  
 |  ----------------------------------------------------------------------
 |  Data and other attributes defined here:
 |  
 |  CLSID = IID('{98898143-96E2-11D3-A1D0-444553540000}')
 |  
 |  CLSID_Sink = IID('{98898143-96E2-11D3-A1D0-444553540000}')
 |  
 |  coclass_clsid = IID('{98898145-96E2-11D3-A1D0-444553540000}')
Nicht das was ich erwarte habe, aber immerhin gibt es die Funktion tatsächlich und sie macht auch was :wink: Seven
Buell
User
Beiträge: 90
Registriert: Samstag 29. Oktober 2005, 14:17

Ich würde mal nachsehen ob Phoner noch andere Schnittstellen hat, sieht mir ganz danach aus...
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

Buell hat geschrieben:Ich würde mal nachsehen ob Phoner noch andere Schnittstellen hat, sieht mir ganz danach aus...
Ja, es hat noch eine ActiveX Schnittstelle (axphoner.ocx). Aber mit ActiveX habe ich mich noch nicht beschäftigt, obwohl es nicht viel anders sein dürfte, als COM. Aber auch da werde ich an die Events wahrscheinlich nur per Callback rankommen. Forsche also noch :) Seven
Benutzeravatar
gerold
Python-Forum Veteran
Beiträge: 5555
Registriert: Samstag 28. Februar 2004, 22:04
Wohnort: Oberhofen im Inntal (Tirol)
Kontaktdaten:

snakeseven hat geschrieben: Aber mit ActiveX habe ich mich noch nicht beschäftigt, obwohl es nicht viel anders sein dürfte, als COM.
Hi Seven!

ActiveX ist nur ein modernerer Ausdruck für COM. Hier findest du eine ziemlich gute Einführung in Python und COM:
http://www.python.org/windows/win32com/ ... pframe.htm

lg
Gerold
:-)
http://halvar.at | Kleiner Bascom AVR Kurs
Wissen hat eine wunderbare Eigenschaft: Es verdoppelt sich, wenn man es teilt.
snakeseven
User
Beiträge: 408
Registriert: Freitag 7. Oktober 2005, 14:37
Wohnort: Berlin
Kontaktdaten:

Hi Gerold,
die Dokumentation kenne ich. Ich finde sie zu minimalistisch und auch unübersichtlich, weil alles in kleinen 'Häppchen' dargeboten wird. Außerdem sind keine Beispiele dabei. Gut finde ich die, die bei Pythonwin on board ist. Übersichtlich und mit Beispielen.
Aber daß ActiveX = COM ist, hat mich veranlasst, mal in gen_py die von makepy generierten Module von "PhonerBibliothek" und "AxPhoner" zu vergleichen. Und da steht tatsächlich fast das Gleiche drin. Und da gibt es auch definitiv keine Eventfunktion "OnChangeState". Es steht nur drin, daß man sich die selber schreiben muß. Wobei sich da die Katze in den Schwanz beißt, weil ich mir die Funktion natürlich selber schreiben kann, aber dennoch braucht diese eigene Funktion eine Schnittstelle zu COM !?
Ich werde mich aber in Zukunft auf Asterisk konzentrieren, da gibt es einfache Textscripte und die werden abgearbeitet.
Gruss, Seven
Antworten