Because the more netizens are now in 9CBS, I have written this question about BCB writing DLL.
Article article throwing brick
I. Write a DLL
File / New / DLL Generates a DLL's wizard, then you can add export functions and export classes
Export function: extern "c" __declspec (dllexport) ExportType FunctionName (Parameter
)
Export class: class __declspec (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 creteaform ();
TDLLFRM * DLLMYFORM;
}
TDLLFRM * DLLMYFORM2;
Extern "C" __declspec (dllexport) __stdcall void createfromFunt (); // Export Letter
number
/ / -------------------------------------------------------------------------------------------- -----------------------
----
Int WinAPI DLLENTRYPOINT (Hinstance Hinst, Unsigned Long Reason, Void *)
{
Return 1;
}
/ / -------------------------------------------------------------------------------------------- -----------------------
----
Mydllclass :: mydllclass ()
{
}
Void mydllclass :: creteaform ()
{
DllmyForm = New TdllFRM (Application);
DllmyForm-> show ();
}
/ / -------------------------------------------------------------------------------------------- -----------------------
----
void __stdcall createfromfunt ()
{
DllmyForm2 = new TDLLFRM (Application);
DllmyFORM2-> show ();
}
Second. Static call DLL
Generate lib files using $ bcb path / bin / implib.exe, join to the project file
Copy the file to the current directory, generate usage use iMPLIB MyDLL.LIB MyDLL.DLL
// Unit1.h // TFORM1 definition
#include "dllform.h" // TDLLFRM definition
/ / -------------------------------------------------------------------------------------------- -----------------------
----
__DECLSPEC (DLLIMPORT) Class __stdcall mydllclass {
PUBLIC:
Mydllclass ();
Void creteaform ();
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 called in static mode
Dllclass = new mydllclass ();
DLLCLASS-> CreateAform ();
}
/ / -------------------------------------------------------------------------------------------- -----------------------
----
Void __fastcall tform1 :: button2click (Tobject * Sender)
{// export function implementation
CreateFromFunct ();
}
/ / -------------------------------------------------------------------------------------------- -----------------------
----
Void __fastcall tform1 :: formclose (Tobject * Sender, Tclosection & Action)
{
DELETE DLLCLASS;
}
3. Dynamic call DLL
// unit1.h
Class TFORM1: Public TForm
{
...
PRIVATE: // user declarations
Void (__stdcall * createfromfromfunct) ();
...
}
// unit1.cpp // TFORM1
Hinstance Dllinst = NULL;
Void __fastcall tform1 :: button2click (Tobject * Sender)
{
IF (null == dllinst) dllinst = loadingLibrary ("dll.dll"); // above DLL
IF (dllinst) {
CreateFromFunct = (Void (__stdcall *) ()) getProcaddress (DLLINST,
"Cretefromfunct");
CreateFromFunct CREATEFROMFUNCT ();
Else ShowMessage ("Could Not Obtain Function Pointer);
}
Else ShowMessage ("Could Not Load Dll.dll);
}
Void __fastcall tform1 :: formclose (Tobject * Sender, Tclosection & Action)
{
IF (dllinst) Freelibrary (DLLINST);
}
Four. DLL as a MDICHILD (Subform) [only to write examples of dynamic calls]
In fact, when calling the DLL of the child form, the system is just check whether the application's mainform is FSMDIFORM.
Form, this only
To pass the call from the calling program to the application to the application;
Recovery when exiting the DLL
Application
// mdichildpro.cpp // DLL implementation CPP
#include "unit1.h" // tform1 definition
Tapplication * SaveApp = NULL;
Int WinAPI DLLENTRYPOINT (Hinstance Hinst, Unsigned Long Reason, Void *)
{
IF ((REASON == DLL_PROCESS_DETACH & SaveApp)
Application = saveApp; // Restore ApplicationReturn 1;
}
Extern "C" __Declspec (dllexport) __stdcall void testmdichild (//1024x768
TAPPLICATION * MainApp,
LPSTR LPCAPTION)
{
IF (null == saveApp) / / Save Application to pass the Application
{
SaveApp = Application;
Application = mainApp;
}
// lpcaption for the CAPTION of the child form
TFORM1 * FORM1 = New TFORM1 (Application, LPCAPTION);
FORM1-> show ();
}
Note: The above program uses BCB 3.0 compiled successfully
5. BCB calls VC written in the DLL
1. Decomposition:
No name decomposition
TestFunction1 // __CDECL CALLING Convention
@ TestFunction2 // __fastcall calling convention
TestFunction3 // __pascal calling convention
TestFunction4 // __stdcall calling conveention
Function with name decomposition
@ TestFunction1 $ qv // __cdecl calling convention
@ TestFunction2 $ qv // __fastcall calling convention
TestFunction3 $ qqrv // __apscal calling convention
@ TestFunction4 $ qqrv // __stdcall calling convention
Use extern "C" without breaking 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 to the identifier to keep
It turns out all the full identifiers. The parameter passes the stack to the stack by the principle of the right one.
Extaern "c" BOOL __CDECL TESTFUNCTION ();
Displayed in the DEF file
TestFunction @ 1
Note: @ 1 indicates the number of functions, will be used when "use alias".
__pascal pascal format
At this time, the function name all turns the uppercase, the first parameter first stack, then clear the stack.
TestFunction @ 1 // DEF file
__stdcall standard call
The last parameter is stack, then clear the stack.
TestFunction @ 1 // DEF file
__fastcall passes the parameters to the register
The first parameter is first stack, then clear the stack.
@TestFunction @ 1 // DEF file
3. Solve the call agreed:
The difference between Microsoft and Borland's __stdcall is naming. Borland
__stdcall's way to get off the next line before the name. Microsoft is before adding underline,
After adding @, follow the number of bytes reserved for the stack. The number of bytes depends on the space occupied by the argument. Every
The parameters are rounded to 4 multiple times. This MiOCrosoft's DLL is different from the system's DLL. 4. Use an alias:
The purpose of using the alias is to make the call file .Obj matches the DLL. DEF file. If not yet
.Def file, you should build one first. Then add the DEF file to Project. Use alias should continue
Modify external errors, if not, you also need to join the Imports section to the DEF file.
Imports
TestFunctiom4 = DLLPRJ.TESTFunction4
TestFunctiom5 = DLLPRJ.WEP @ 500
Testfunctiom6 = DLLPRJ.GETHOSTBYADDR @ 51
What needs to be described here is that the .Obj name and DLL of the application is equivalent,
And always like this. It doesn't even consider calling conventions, it will automatically match. In the previous example, the function is
The description is __pascal, thus generates a capital function name. 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 loading vc_win32 dll by __fastcall mode
IS OK! ";
Return StrretfastCall;
}
In fact, dynamic calls are not distinguished from the DLL written by calling BCB. The key is to view the DLL export function name.
You can view TDUMP.EXE (BCB Tools) or Dumpbin.exe (VC Tool)
TDump -ee mydll.dll> 1.txt (view 1.txt file)
Since the VC6 does not support __pascall mode, the following example will be given.
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 = loadingLibrary ("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't Find The __stddcall 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, you can know the name of the export function from the dynamic call, but direct time (join lib)
Document to the project file)
Linker prompts cannot find the implementation of the function
As seen from 4, you can join the DEF file connection
(You can get the export table via IMPDEF MYDLL.DEF MYDLL.DLL)
Establish the same DEF file with the DLL file name to join the project file with the lib file
The DEF file of the above DLL (vcwin32.dll) is (vcwin32.def):
Library vcwin32.dll
Imports
@ Bcbloadvcwin32fastcall = vcwin32. @ Bcbloadvcwin32fastcall @ 0
_Bcbloadvcwin32cdecl = vcwin32.bcbloadvcwin32cdecl
BCBLOADVCWIN32STDCALL = vcwin32._bcbloadvcwin32stdcall@0
The corresponding function declaration and implementation are as follows:
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, you may directly press F9 or pass Linker, please first build.
Note: The above program uses BCB 5.0 and the VC6.0 compiled successfully