Newsgroup: it.comp.lang.c++
Titolo: Aiuto per funzioni statiche e callback

Ciao ragazzi,
ricordo che tempo fa si discusse dei meccanismi di callback. 
Rinfrescatemi le idee.
In un mio programma ho la necessita' di sfruttare una funzione di
callback che viene richiamata dal sistema (Windows).
Io l'ho dichiarata come membro statico della classe ma, chiaramente,
da essa non posso accedere ai membri privati della classe.
Come posso fare ?
Per il momento ho risolto dichiarando una variabile globale per ogni
membro private della classe ma questo mi sembra andare contro tutti i
sani principi di information hiding (!).
Qualcosa del tipo :
static int GlobalInteger ;
class MiaClasse {
 
      private:
         static void cb_function() ;
      public:
         int get_value() ;
} ;
void MiaClasse::cb_function()
{
     GlobalInteger = 5 ;   
}
int MiaClasse::get_value()
{
    return GlobalInteger ;
}
Chiaramente la visibilita' di GlobalInteger e' limitata al modulo .cpp
in cui e' definita (grazie a static), ma non mi sembra una soluzione
accettabile.
Alternative ?
-- 
Andrea Laforgia (ICQ# 87230455) ---------------------------
Non scrivetemi in privato, se non richiesto espressamente.
No replies in private e-mail, unless explicitly requested.
----------------------------------------------------------

 Come posso fare ?
Non sono un 'esperto di programmazione Windows,ma se il sistema ha la
facolta' di accedere ad un membro funzione privato statico,
dichiarando le tue variabili come membri privati statici non ci dovrebbero
essere problemi.
--
Ivan Molella (icq# 97960484)
__LINUX__ the choice of the __GNU__ generation

essere problemi.
In realta' la programmazione per Windows c'entra poco.
L'uso di variabili membro statico l'avevo gia' preso in
considerazione, ma non va bene. Infatti conservo la dichiarazione
della classe in un file .h e la definizione dei metodi nel rispettivo
.cpp. Devo necessariamente portare i membri statici al di fuori nel
file .cpp, altrimenti i metodi non riescono a gestirli.


Non ho ben capito perche' non potresti fare una cosa del tipo:
MiaClasse.h
---------------------
#ifndef    MIACLASSE_H
#define   MIACLASSE_H
class MiaClasse {
      static int GlobalInteger;
      static void cb_function() ;
public:
         int get_value() ;
} ;
#endif  //MIACLASSE_H
MiaClasse.cpp
------------------
#include"MiaClasse.h"
int MiaClasse::GlobalInteger;
void MiaClasse::cb_function()
{
     GlobalInteger = 5 ;
}
int MiaClasse::get_value()
{
    return GlobalInteger ;
}


 da essa non posso accedere ai membri privati della classe.
Ma che senso ha accedere ai membri privati della classe se non stai
creando alcuna istanza? Forse dovresti invece definire membri statici da
utilizzare attraverso la funzione statica di callback.
EMG

Ma qual'è il problema?
Stabilire l'eventuale istanza della classe che ha chiamato (indirettamente)
la funzione statica, all'interno della funzione statica stessa?
Se non è questa la domanda, mi scuso in anticipo per avervi fatto perdere
tempo nel leggere fino a questo punto.
Se è così, praticamente tutte le API windows mettono a disposizione un
parametro aggiuntivo, che viene passato alle callback.
In genere si utilizza questo parametro per passare il puntatore della
classe (this) alla callback - la quale può tranquillamente riconoscere
l'istanza della classe su cui sta operando.
Ad esempio, ammettiamo di volere mettere in un array le finestre
child di una data finestra. Per fare questo utilizziamo una classe
chiamata CWindowCollection, invocando la API EnumChild.
La callback di EnumChild dovrà essere necessariamente una funzione
statica, perchè Windows funziona così, ma grazie al parametro
extra si può evitare con un minimo di sforzo l'utilizzo di
perigliose variabili globali.
class CWindowCollection
{
 public:
  CWindowCollection(HWND hWndParent);
  static BOOL CALLBACK funzione_statica (HWND hWndChild, DWORD dwUser);
  BOOL CALLBACK funzione_non_statica (HWND hWndChild);
  int getWindowCount() { return _windowCount; }
  HWND getWindowHandle(int n)
  {
   assert(n>= 0 && n < _windowCount);
   return _hWndArray[n];
  }
 private:
  HWND _hWnd;
  int _windowCount;
  HWND _hWndArray[256];
};
CWindowCollection::CWindowCollection(HWND hWndParent)
 : _hWnd(hWndParent), _windowCount(0)
{
 /* passa this alla callback */
 EnumChildProc(funzione_statica, (LPARAM)this);
}
BOOL CALLBACK
CWindowCollection::funzione_statica (HWND hWndChild, LPARAM lp)
{
 BOOL bRet = FALSE;
 /* Riconosce l'istanza di CWindowCollection */
 CWindowCollection* This = (CWindowCollection*)lp;
 /* Chiama la funzione non statica */
 if (This)
    bRet = This->funzione_non_statica(hWndChild, lp);
 return bRet;
}
/* Callback */
BOOL
CWindowCollection::funzione_non_statica (HWND hWndChild)
{
 This->_hWndArray[This->_windowCount] = hWndChild;
 ++This->_windowCount;
 return (_windowCount < 256);
}

parametro aggiuntivo, che viene passato alle callback.
Grazie dell'interessamento, ma non e' questo il caso.


Non ho ben capito perche' non potresti fare una cosa del tipo:
<snip codice>
Grazie, faro' cosi' ;)


utilizzare attraverso la funzione statica di callback.
Infatti ;)


 prescindere da qualsiasi istanza reale.
Mi sono espresso male. Volevo dire che utilizzando solo una funzione
static di callback non crei alcuna istanza di quella classe in run-time
e quindi non ha senso pensare di accedere ai membri privati non static.
Di quale inesistente istanza sarebbero membri?
EMG

Di quale inesistente istanza sarebbero membri?
Hai ragione e mi sono espresso male anch'io.
In realta' i membri privati a cui faccio riferimento, sono dei membri
anch'essi statici e quindi unici per classe.
Il problema e' che voglio mascherare un po' l'accesso ai dati.
Mi spiego, l'SDK che sto utilizzando (e' un pacchetto di
riconoscimento vocale) lavora con funzioni di callback perche' procede
in modo asincrono. Ora, il meccanismo che devo implementare e' il
seguente :
1. Apro il file .wav.
2. Leggo le informazioni contenute.
3. Apro il motore di riconoscimento.
4. Passo le informazioni lette dal file.
5. Salvo il valore restituitomi (il testo).
6. Chiudo tutto
Il problema e' che il passaggio 4 e' subordinato alla corretta
esecuzione del passaggio 3, il cui esito mi arriva per mezzo di una
funzione di callback e il 5 anche, perche' il valore mi viene
restituito sempre per funzione di callback.


riconoscimento vocale)
Ma funziona questo riconoscimento vocale o è come quelli che provai ai
tempi che ci vuole un anno per istruirli e 2 minuti per disinstallarli
dalla disperazione? ^___^
Luc.

dalla disperazione? ^___^
I miei programmi sono infallibili ;)


I miei programmi sono infallibili ;)
Hai implementato tu gli algoritmi di riconoscimento vocale?
Luc.

Hai implementato tu gli algoritmi di riconoscimento vocale?
No, scherzavo ;) gli algoritmi sono della Lernout & Hauspie e sembrano
essere affidabili (sembrano). Ora pero' siamo OT ;)
