BCB writing DLL ultimate manual

zhaozj2021-02-16  61

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

转载请注明原文地址:https://www.9cbs.com/read-17860.html

New Post(0)