BCB writing DLL ultimate manual
1. Write a DLL File / New / DLL to generate a DLL guide, then add export functions and export class export functions: ExportType FunctionName (DLLEXPORT) exporttype classname {. ..} example: (Description: Just generate a DLL.dll)
#include "dllform.h" // TDLLFRM definition
Useres ("DLL.RES"); UseForm ("DLLFORM.CPP", DLLFRM);
Class __declspec (dllexport) __stdcall mydllclass {// Export class public: mydllclass (); void createaform (); TDLLFRM * DLLMYFORM;};
TDLLFRM * DLLMYFORM2; Extern "C" __declspec (dllexport) __stdcall void createFromFunt (); // Export function
/ / -------------------------------------------------------------------------------------------- --------------------------- Int WinApi DLLENTRYPOINT (Hinstance Hinst, Unsigned Long REason, Void *) {Return 1;} // -------------------------------------------------- -----------------------
MYDLCLASS :: mydllclass () {}
Void mydllclass :: createaform () {dllmyform = new tdllfrm (application); dllmyform-> show ();} // -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------------------------------- - void __stdcall createfromFunt () {dllmyform2 = new tdllfrM (application); dllmyform2-> show ();
II. Static call DLL Generate lib files using $ bcb path / bin / implib.exe, add this file to the current directory in the project file, generate // unit1.h // TFORM1 definition using IMPLIB MyDLL.LIB MyDLL.DLL #include "dllform.h" // TDLLFRM definition // ------------------------------------- -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
__declspec (dllimport) class __stdcall MyDllClass {public: MyDllClass (); void CreateAForm (); TDllFrm * DllMyForm;}; extern "C" __declspec (dllimport) __stdcall void CreateFromFunct ();
Class TFORM1: PUBLIC TFORM {...}
// Unit1.cpp // TFORM1 Implement Void __fastcall tform1 :: button1click (TOBJECT * Sender) {// Export class implementation, export classes can only be used to call DLLClass = new mydllclass (); dllclass-> createaform ();} / / -------------------------------------------------------------------------------------------- --------------------------- void __fastcall tform1 :: button2click (TOBJECT * Sender) {// Export function implementation creteFromFunct ();} / / --------------------------------------------------- -------------------------- void __fastcall tform1 :: formclose (TCLOSEACTION & ACTION) {Delete Dllclass;
3. Dynamic call DLL // unit1.h class tform1: public tform {... private: // user declarations void (__stdcall * createfromfunct) (); ...}
// Unit1.cpp // TFORM1 Hinstance Dllinst = NULL; VOID __FASTCALL TFORM1 :: Button2Click (TOBJECT * Sender) {if (null == dllinst) Dllinst = loadingLibrary ("dll.dll"); // DLL IF above ( DLLInst) {CreateFromFunct = (void (__stdcall *) ()) GetProcAddress (DLLInst, "CreateFromFunct"); if (CreateFromFunct) CreateFromFunct (); else ShowMessage ( "Could not obtain function pointer");} else ShowMessage ( "Could not Load dll.dll ");
Void __fastcall tform1 :: formclose (TCLOSEACT * Sender, TcloseAction & Action) {if (dllinst) Freelibrary (DLLINS);
IV. DLL as a MDICHILD (Sub-form) [Examples of Dynamic Call on Dynamic Calls] In fact, when the Subform DLL is called, the system is just check whether the application's mainform is FSMDIFORM form, which only
To pass the APPLICE of the calling program to the application; if you want to recover when you exit the DLL
Application
// MDIChildPro.cpp // Dll achieve CPP #include "unit1.h" // TForm1 defined TApplication * SaveApp = NULL; int WINAPI DllEntryPoint (HINSTANCE hinst, unsigned long reason, void *) {if ((reason == DLL_PROCESS_DETACH) & SaveApp) Application = SaveApp; // Restore Application Return 1;}
extern "C" __declspec (dllexport) __stdcall void TestMDIChild (// 1024X768 TApplication * mainApp, LPSTR lpCaption) {if (NULL == SaveApp) // save Application, transfer Application {SaveApp = Application; Application = mainApp;} // lpCaption CAPTION TFORM1 * FORM1 = New TFORM1 (LPCAPTION); FORM1-> show ();} Note: The above program is compiled using BCB 3.0. BCB calls VC written DLL 1. Name Decomposition: No name resolution functions TestFunction1 // __cdecl calling convention @ TestFunction2 // __fastcall calling convention TESTFUNCTION3 // __pascal calling convention TestFunction4 // __stdcall calling convention with the name of the decomposition function @ TestFunction1 $ QV // __cdecl calling convention @ TestFunction2 $ qv // __fastcall Calling Convention TestFunction3 $ qrv // __apscal calling convention @ TestFunction4 $ qrv // __stdcall calling convention Use extern "C" not to decompose the function name
Generate a DEF file to see if the name decomposition is used using the ompdef mylib.def mylib.dll.
2. Call the agreement: __cdecl default is the default C format naming agreement of Borland C , which adds a scribe in front of the identifier to keep it the original identifier. The parameter passes the stack to the stack by the principle of the right one. Extaern "c" BOOL __CDECL TESTFUNCTION (); displayed as testfunction @ 1 in the DEF file: @ 1 indicates the number of functions, will be used when "use alias".
__pascal pascal format This time the function name is all turned to uppercase, the first parameter first stack, then clear the stack. TestFunction @ 1 // DEF file
__stdcall standard call the last parameter first stack, then clear the stack. TestFunction @ 1 // DEF file
__fastcall passes the parameters to the first parameter of the register first stack, then clear the stack. @TestFunction @ 1 // DEF file
3. Resolve the call agreement: The difference between Microsoft and Borland's __stdcall is naming. Borland's way of __stdcall removed the next line before the name. Microsoft is before adding underline, add @, then follow the number of bytes reserved for the stack. The number of bytes depends on the space occupied by the argument. Each parameter is rounded up to 4 multiple times. This MiOCrosoft's DLL is different from the system's DLL.
4. Using an alias: Use the purpose of using the alias to make the call file .Obj matched with the DLL. DEF file. If there is no .def file, you should build one first. Then add the DEF file to Project. Use the alias should constantly modify external errors, if not, you also need to add the imports section to the DEF file. Imports testfunctiom4 = DLLPRJ.TESTFUNCTION4 TESTFUNCTIOM5 = DLLPRJ.WEP @ 500 TestFunctiom6 = DLLPRJ.GETHOSTBYADDR @ 51 Here you need to explain that calling applications. Obj name and DLL's .def file name is equivalent, and always. It doesn't even consider calling conventions, it will automatically match. In the previous example, the function is illustrated as __pascal, thus generating uppercase function names. This link will not be wrong. 5. Dynamic call example The code of the VC DLL is as follows: Extern "C" __DECLSPEC (DLLEXPORT) LPSTR __STDCALL BCBLOADVCWIN32STDCALL () {static char strretstdcall [256] = "bcb load vc_win32 dll by __stdcall mode is ok!";
Return Strretstdcall;}
Extern "c" __declspec (dllexport) LPSTR __CDECL BCBLOADVCWIN32CDECL () {static char strretcdecl [256] = "BCB LOAD VC_WIN32 DLL BY __CDECL MODE IS OK!";
Return strretcdecl;
Extern "C" __declspec (dllexport) LPSTR __FASTCALL BCBLOADVCWIN32FASTCALL () {static char strretfastcall [256] = "BCB LOAD VC_WIN32 DLL BY __FASTCALL MODE IS OK!";
Return strretfastcall;}
In fact, dynamic calls and DLLs written by calling BCB do not differ, the key is to view the DLL export function name to view TDUMP -EE MyDLL.DLL> 1.TXT (View "or DUMPBIN.EXE (VC tool) 1.TXT files can be) Since the VC6 does not support __pascall mode, the following three ways of example void __fastcall tform1 :: btnblvcwin32dynclick (Tobject * sender) {/ * cmd: tdbump vcwin32.dll> 1.txt Turbo Dump Version 5.0.16.4 Copyright (c) 1988, 1998 Borland International Display of File Vcwin32.dll
EXPORT ord: 0000 = 'BCBLoadVCWin32Fastcall ::' EXPORT ord: 0001 = 'BCBLoadVCWin32Cdecl' EXPORT ord: 0002 = '_ BCBLoadVCWin32Stdcall @ 0' * / if (DllInst!) DllInst = LoadLibrary ( "VCWin32.dll"); if (DllInst) {BCBLoadVCWin32Stdcall = (LPSTR (__stdcall *) ()) GetProcAddress (DllInst, "_BCBLoadVCWin32Stdcall @ 0"); // VC Dll // GetProcAddress (DllInst, "BCBLoadVCWin32Stdcall"); // BCB Dll if (BCBLoadVCWin32Stdcall) {ShowMessage (BCBLoadVCWin32Stdcall ());} else ShowMessage ( "Can not find the __stdcall Function!"); BCBLoadVCWin32Cdecl = (LPSTR (__cdecl *) ()) GetProcAddress (DllInst, "BCBLoadVCWin32Cdecl"); if (BCBLoadVCWin32Cdecl) {ShowMessage (BCBLoadVCWin32Cdecl () } Else ShowMessage ("Can't Find The __cdecl function!");
// Why? Is not 'bcbloadvcwin32fastcall ::', but '@ bcbloadvcwin32fastcall @ 0'? BCBLoadVCWin32Fastcall = (LPSTR (__fastcall *) ()) // GetProcAddress (DllInst, "BCBLoadVCWin32Fastcall ::"); GetProcAddress (DllInst, "@ BCBLoadVCWin32Fastcall @ 0"); if (BCBLoadVCWin32Fastcall) {ShowMessage (BCBLoadVCWin32Fastcall ());} else ShowMessage ("Can't Find The __fastcall function!");} Else ShowMessage ("Can't Find The DLL!");
6. Static call example static call is a bit trouble, from the dynamic call, you can know the name of the export function, but directly (join the lib file to the project file)
The Linker prompt cannot find the implementation of the function from 4, you can join the DEF file connection (you can get the export table via the impdef mydll.def mydll.dll) to establish the same DEF file with the DLL file name to join the lib file to the project file. DEF files of DLL (Vcwin32.dll) are (vcwin32.def): library vcwin32.dll
. IMPORTS BCBLoadVCWin32Fastcall = VCWIN32 BCBLoadVCWin32Fastcall @ 0 _BCBLoadVCWin32Cdecl = VCWIN32.BCBLoadVCWin32Cdecl BCBLoadVCWin32Stdcall = VCWIN32._BCBLoadVCWin32Stdcall@0 @@ corresponding function declarations and to achieve the following: extern "C" __declspec (dllimport) LPSTR __fastcall BCBLoadVCWin32Fastcall (); extern "C" __declspec ( Dllimport) LPSTR __CDECL BCBLOADVCWIN32CDECL (); Extern "C" __DECLSPEC (DLLIMPORT) LPSTR __STDCALL BCBLOADVCWIN32STDCALL ();
void __fastcall TfrmStatic :: btnLoadDllClick (TObject * Sender) {ShowMessage (BCBLoadVCWin32Fastcall ()); ShowMessage (BCBLoadVCWin32Cdecl ()); ShowMessage (BCBLoadVCWin32Stdcall ());} Note: in BCB 5.0, it may not directly press F9 by Linker , Please first, BUILD, check: The above program uses BCB 5.0 and VC6.0 compiles successful