Newsgroup: it.comp.lang
Titolo: [PYTHON] callback con dll

Sto sperimentando in python 2.2.2 e wxPython 2.3 l'uso di una dll per la
manipolazione di file in formato dxf che finora ho impiegato sempre
tramite visual basic 6.
Devo dire che con "caddll" e "windll" di Sam Rushing sta funzionando
tutto a perfezione. L'unico problema che non sono riuscito a risolvere
e' come impostare una funzione di callback per rispondere agli eventi
generati dalla dll.
In visual basic avrei usato l'operatore AddressOf:
'implementazione della funzione di callback
Public Sub CallBackForMouseMove (hDwg As Long, _
                                                 Button As Integer, _
                                                 Key As Integer, _
                                                 Xwin As Ineteger, _
                                                 Ywin As Inetger, _
                                                 Xdwg As Double, _
                                                 Ydwg As Double, _
                                                 Zdwg As Double)
End Sub
'registrazione della mia funzione di callback tramite la dll
CadOnEventMouseMove AddressOf CallBackForMouseMove
Come potrei fare la stessa cosa in Python???
Ho dato un'occhiata al modulo gencb.py sempre di Sam Rushing, ma non ho
capito niente del suo funzionamento!!!
Grazie per l'attenzione,
tragick

 generati dalla dll.
Forse e` piu` semplice con la piu` nuova ctypes, 
http://starship.python.net/crew/theller/ctypes/tutorial.html
Non ho mai avuto bisogno di callback ne` con calldll ne` con ctypes,
quindi non ho esperienza diretta, ma con ctypes sembra facilissimo,
ad esempio per chiamare la qsort della libreria standard C su di
un array di interi si prepara la funzione di callback con:
      from ctypes import CFunction, c_int
      class CMPFUNC(CFunction):
          _types_ = "ii"
          _stdcall_ = 0
      def compare(a1, a2):
          v1 = c_int.from_pointer(a1).value
          v2 = c_int.from_pointer(a2).value
          return cmp(v1, v2)
      cmpfunc = CMPFUNC(compare)
Alex


Innanzi tutto ti ringrazio per l'ottimo consiglio e per la velocita' con
cui me lo hai dato.
Ho scaricato ctypes ed in effetti risulta semplicissimo da usare!
Purtroppo pero', c'e' un "ma" credo irrisolvibile. :(
Come dicevo nel posto iniziale, avevo bisogno di utilizzare una funzione
di callback per catturare gli eventi del mouse prodotti da una dll che
gestisce contesti grafici vettoriali. Con ctypes riesco facilmente
nell'intento, ma alla fine qualcosa interferisce con il normale
funzionamento della libreria. Ad esempio, un click del tasto destro del
mouse sull'area grafica produce un menu' contestuale; se pero' registro
una funzione di callback associata all'evento di click allora il menu'
contestuale non compare in prossimita' del puntatore del mouse, ma viene
sbattuto agli estremi dello schermo!!!
Grazie ancora,
tragick

 sbattuto agli estremi dello schermo!!!
Boh, naturalmente non posso avere nessuna idea delle cause.  Ma puzza
che stai lasciando a zero qualcosa che dovrebbe essere settato in modo
diverso, o VV.  Scrivi il piu` semplice possibile esempio di programmino
che usa quella libreria e quella callback, magari prima in C, e vedi di
farlo funzionare, poi traslitteralo "bit per bit" in ctypes e Python.
Insomma, riproduci il bug IN PICCOLO, in piccolissimo, come si fa per
dare la caccia a qualsiasi bug misterioso ovviamente.
Alex


In effetti ho tentato di procedere in questo modo, ma il nocciolo del
problema mi rimane ugualmente celato. Questo e' un esempio minimale e
funzionante in visual basic da inserire nell'evento load di un form:
------------------ codice vb ---------------------
    Dim CadObj As Long
    Dim CadWnd As Long
    CadRegistration 0
    CadObj = CadCreate()
    CadOnEventMouseDown AddressOf CallBackForMouseClick
    CadWnd = CadWndCreate(CadObj, Me.hWnd, 0, 0, 0, Me.ScaleWidth,
Me.ScaleHeight)
    CadFileOpen CadObj, CadWnd, "d:\villa.vec"
----------------------------------------------------------------------
N.B.: "CallBackForMouseClick" e' definita come sub vuota in un modulo
bas.
Questa e' la traduzione python che produce comportamenti anomali:
--------------- codice python ----------------------------
class CBMouse(CFunction):
    _types_ = 'iiiiiiii'
    _stdcall_ = 0
def MouseDownProc (hDwg, Button, Key, Xwin, Ywin, Xdwg, Ydwg, Zdwg):
        pass
callfunc = CBMouse(MouseDownProc)
class MainWindow(wxFrame):
    def __init__(self):
        wxFrame.__init__(self, None, -1, "PyCAD", size=(350, 310),
               style=wxCAPTION|wxSYSTEM_MENU|wxMINIMIZE_BOX)
        self.Layout()
class PyCAD(wxApp):
    def OnInit(self):
        mw = MainWindow()
        mw.Show(1)
        mw.CentreOnScreen()
        try:
            vc = windll.Cad
            vc.CadRegistration(0)
            CadObj = vc.CadCreate()
            CadWnd = vc.CadWndCreate(CadObj, mw.GetHandle(), 0, 0, 0,
                             mw.GetClientSizeTuple()[0],
                             mw.GetClientSizeTuple()[1])
            res = vc.CadFileOpen(CadObj, CadWnd, 'd:\\villa.vec')
            vc.CadOnEventMouseDown(callfunc)
        except Exception, s:
            print s
        return 1
-----------------------------------------------------------
Le uniche osservazioni che sono in grado di fare sono:
(1) il tipo degli argomenti accettati dalla funzione di callback e
introdotti dalla variabile _types_ della classe CBMouse sono 8 interi
mentre dovrebbero essere 5 interi e 3 double, ma a quanto ho capito i
double non sono supportati.
(2) la variabile _stdcall_ della classe CBMouse influenza il modo in cui
la funzione di callback viene chiamata. Se _stdcall_ == 0 allora il menu
contestuale scaturito con la pressione del tasto destro del mouse mi
compare a seconda della posizione del puntatore ho sul bordo superiore
dello schermo o su quello inferiore. Se metto _stdcall_ a 1 invece il
menu contestuale appare invariabilmente attaccato al bordo destro dello
schermo.
Prima di salutarti auguro buona pasqua a te e a tutti i niusgruppari.
Ciao,
tragick