Creation de DLL en C/C++ |
__declspec(dllexport) __declspec(dllimport)Une DLL contient le même code qu'un exécutable mais les déclarations des symboles sont préfixées par une directive d'exportation.
// Fichier CustomDll.h #ifdef CUSTOMDLL_EXPORTS #define CUSTOMDLL_API __declspec(dllexport) #else #define CUSTOMDLL_API __declspec(dllimport) #endif CUSTOMDLL_API BOOL GetFileTimeByName( LPCSTR lpszFile, FILETIME * ftCreate, FILETIME * ftAccess, FILETIME * ftWrite );Le code de la DLL déclare la constante CUSTOMDLL_EXPORTS et fait un #include du fichier.
BOOL WINAPI DllMain( HINSTANCE hinstDLL, // handle to the DLL module DWORD fdwReason, // reason for calling function LPVOID lpvReserved // reserved );
Il existe quatre raisons pour lesquels cette fonction est appelée:
- DLL_PROCESS_ATTACH : le processus (EXE) courant charge la DLL
- DLL_THREAD_ATTACH : le processus courant créé un nouveau thread
- DLL_THREAD_DETACH : un thread du processus courant se termine
- DLL_PROCESS_DETACH : la DLL est déchargée du processus courant
La compilation du projet de la DLL produit un fichier DLL et un fichier
d'extension LIB. Pour charger de manière statique une DLL, le programme client peut ajouter ce
fichier d'extension LIB à son projet ou bien utiliser la directive de
compilation suivante:
#pragma comment(lib, "..\\CustomDll\\Release\\CustomDll.lib")Voici le code de l'application client :
// TestCustomDll.cpp : Defines the entry point for the console application. // #include <stdio.h> #include <windows.h> #include "..\\CustomDll\\CustomDll.h" #pragma comment(lib, "..\\CustomDll\\Release\\CustomDll.lib") int main(int argc, char* argv[]) { FILETIME ftCreate, ftAccess, ftWrite; SYSTEMTIME stCreate, stAccess, stWrite; char szWinDir[255]; char szFile[255]; GetWindowsDirectory(szWinDir, 255); sprintf(szFile, "%s\\EXPLORER.EXE", szWinDir); if( GetFileTimeByName( szFile, &ftCreate, &ftAccess, &ftWrite) == FALSE ) { printf("GetFileTimeFrom failed\n"); return 0; } FileTimeToSystemTime(&ftCreate, &stCreate); FileTimeToSystemTime(&ftAccess, &stAccess); FileTimeToSystemTime(&ftWrite, &stWrite); printf("File:%s, Create DateTime:%02d/%02d/%02d %02d:%02d:%02d\n", szFile, (int)stCreate.wDay, (int)stCreate.wMonth, (int)stCreate.wYear, (int)stCreate.wHour, (int)stCreate.wMinute, (int)stCreate.wSecond); printf("File:%s, Access DateTime:%02d/%02d/%02d %02d:%02d:%02d\n", szFile, (int)stAccess.wDay, (int)stAccess.wMonth, (int)stAccess.wYear, (int)stAccess.wHour, (int)stAccess.wMinute, (int)stAccess.wSecond); printf("File:%s, Write DateTime:%02d/%02d/%02d %02d:%02d:%02d\n", szFile, (int)stWrite.wDay, (int)stWrite.wMonth, (int)stWrite.wYear, (int)stWrite.wHour, (int)stWrite.wMinute, (int)stWrite.wSecond); return 0; }Lorsque la DLL est construite pour être utilisée aussi bien en C qu'en C++, il faut que la déclaration des symboles soit encapsulées dans un bloc extern "C" décrit comme suit:
// Fichier CustomDll.h #ifdef CUSTOMDLL_EXPORTS #define CUSTOMDLL_API __declspec(dllexport) #else #define CUSTOMDLL_API __declspec(dllimport) #endif #ifdef __cplusplus extern "C" { CUSTOMDLL_API BOOL GetFileTimeByName( LPCSTR lpszFile, FILETIME * ftCreate, FILETIME * ftAccess, FILETIME * ftWrite ); } #else CUSTOMDLL_API BOOL GetFileTimeByName( LPCSTR lpszFile, FILETIME * ftCreate, FILETIME * ftAccess, FILETIME * ftWrite ); #endif