Ricordo che un programma scritto in C, per usufruire di una funzione di una DLL, normalmente, ha bisogno di :
1) conoscerne la firma, ovvero il nome della funzione, il tipo di dato restituito, i parametri in numero e tipo (queste informazioni sono normalmente contenute nei file header, i file con estensione .h e sono utilizzate in fase di compilazione)
2) utilizzare la corrispondente Import Library, un file con estensione .LIB che non contiene il codice effettivo della funzione ma le informazioni necessarie perché in fase di linking e loading l'eseguibile risultante possa caricare la giusta DLL e puntare al corretto indirizzo.
Ad esempio, per capire meglio, poniamo il caso che il nostro programma sia
che ottiene i dati di versione del sistema operativo e utilizza la funzione GetVersion della libreria dinamica kernel32.dll
Per quanto riguarda il punto 1), la sua firma è contenuta nel file header winbase.h (a sua volta incluso in windows.h posto all'inizio del codice) ovvero
WINBASEAPI DWORD WINAPI GetVersion (VOID);
in cui le informazioni fondamentali sono il nome stesso della funzione (GetVersion), il tipo di dato restituito (DWORD, un valore a 32 bit) e il numero e tipo dei parametri accettati (VOID, ovvero nessun parametro)
Dopo la fase di compilazione, il linker si occuperà di cercare tra librerie indicate (i file .lib indicati come Import Library) quella in cui sono contenute le informazioni della funzione GetVersion.
A questo punto, includerà nell'eseguibile (in una tabella detta Import Table) il nome della DLL (kernel32.dll) con i nomi delle funzioni e i loro indirizzi relativi (entry point) nella dll stessa.
Questo permetterà al linker di trasformare correttamente la linea
DWORD osv = GetVersion();
in
FF 15 C4 81 41 00 call dword ptr [__imp__GetVersion@0 (4181C4h)]
in cui all'indirizzo 4181C4 della Import Table verrà posto l'indirizzo definitivo della GetVersion (ovviamente questo valore, 4181C4 può variare da programma a programma ...).
L'indirizzo definitivo (proprio perché il linking è dinamico) si otterrà solo all'inizio dell'esecuzione del file exe.
Sarà il Loader del sistema operativo a calcolare ed inserire i valori finali (semplificando) in questo modo :
1) otterrà l'indirizzo virtuale di base in cui è caricata la DLL (supponiamo che la kernel32.dll sia caricata a partire dall'indirizzo 7C800000)
2) sommerà il valore dell'Entry Point per la funzione GetVersion trovata nella Import Table (ottenibile con un programma come Depends), ad esempio per XP SP3, 1127A
3) otterrà il valore 7C81127A che verrà depositato nella Import Table all'indirizzo 4181C4 che è esattamente dove la
call dword ptr [__imp__GetVersion@0 (4181C4h)] [/b]
si aspetta di trovare il codice della GetVersion e che verrà eseguita.
Se vi è tutto chiaro, in un prossimo post vedremo come lavorare "dinamicamente" con le funzioni delle DLL, dal supporto offerto da Windows per questo tipo di lavoro e come questo tipo di uso delle funzioni delle DLL sia a volte necessario.
Per chiarimenti e approfondimenti e per rendere questa sezione un po' più interessante ... commentate ...
1) conoscerne la firma, ovvero il nome della funzione, il tipo di dato restituito, i parametri in numero e tipo (queste informazioni sono normalmente contenute nei file header, i file con estensione .h e sono utilizzate in fase di compilazione)
2) utilizzare la corrispondente Import Library, un file con estensione .LIB che non contiene il codice effettivo della funzione ma le informazioni necessarie perché in fase di linking e loading l'eseguibile risultante possa caricare la giusta DLL e puntare al corretto indirizzo.
Ad esempio, per capire meglio, poniamo il caso che il nostro programma sia
Codice:
Perfavore,
Entra
oppure
Registrati
per vedere i codici!
che ottiene i dati di versione del sistema operativo e utilizza la funzione GetVersion della libreria dinamica kernel32.dll
Per quanto riguarda il punto 1), la sua firma è contenuta nel file header winbase.h (a sua volta incluso in windows.h posto all'inizio del codice) ovvero
WINBASEAPI DWORD WINAPI GetVersion (VOID);
in cui le informazioni fondamentali sono il nome stesso della funzione (GetVersion), il tipo di dato restituito (DWORD, un valore a 32 bit) e il numero e tipo dei parametri accettati (VOID, ovvero nessun parametro)
Dopo la fase di compilazione, il linker si occuperà di cercare tra librerie indicate (i file .lib indicati come Import Library) quella in cui sono contenute le informazioni della funzione GetVersion.
A questo punto, includerà nell'eseguibile (in una tabella detta Import Table) il nome della DLL (kernel32.dll) con i nomi delle funzioni e i loro indirizzi relativi (entry point) nella dll stessa.
Questo permetterà al linker di trasformare correttamente la linea
DWORD osv = GetVersion();
in
FF 15 C4 81 41 00 call dword ptr [__imp__GetVersion@0 (4181C4h)]
in cui all'indirizzo 4181C4 della Import Table verrà posto l'indirizzo definitivo della GetVersion (ovviamente questo valore, 4181C4 può variare da programma a programma ...).
L'indirizzo definitivo (proprio perché il linking è dinamico) si otterrà solo all'inizio dell'esecuzione del file exe.
Sarà il Loader del sistema operativo a calcolare ed inserire i valori finali (semplificando) in questo modo :
1) otterrà l'indirizzo virtuale di base in cui è caricata la DLL (supponiamo che la kernel32.dll sia caricata a partire dall'indirizzo 7C800000)
2) sommerà il valore dell'Entry Point per la funzione GetVersion trovata nella Import Table (ottenibile con un programma come Depends), ad esempio per XP SP3, 1127A
3) otterrà il valore 7C81127A che verrà depositato nella Import Table all'indirizzo 4181C4 che è esattamente dove la
call dword ptr [__imp__GetVersion@0 (4181C4h)] [/b]
si aspetta di trovare il codice della GetVersion e che verrà eseguita.
Se vi è tutto chiaro, in un prossimo post vedremo come lavorare "dinamicamente" con le funzioni delle DLL, dal supporto offerto da Windows per questo tipo di lavoro e come questo tipo di uso delle funzioni delle DLL sia a volte necessario.
Per chiarimenti e approfondimenti e per rendere questa sezione un po' più interessante ... commentate ...