Creating a DLL. Loading DLL in delphi application


I bring to your attention the next issue of the newsletter, in which I continue to discuss
issues of developing and using DLLs in Borland Delphi. For new subscribers I inform you,
that they can look at the first part of the article in the mailing archive, issue number 13.
I apologize to those who wrote to me but did not receive a response. I'll try to fix this in the near future.
So let's continue.

Before you start using any procedure or function located in a dynamic library,
you need to load the DLL in RAM. The library can be loaded
one of two ways: static loading and dynamic loading.
Both methods have both advantages and disadvantages.
Static loading means that the dynamic library is loaded automatically
when the application using it is launched. To use this download method,
you need to use the external keyword when describing what is being exported from
dynamic library function or procedure. The DLL is automatically loaded when start of the program,
and you can use any routines exported from it in the same way as
as if they were described inside application modules.
This is the most easy way using code placed in a DLL.
The disadvantage of this method is that if the library file on which
there is a link in the application, if it is missing, the program will refuse to load.
The point of the dynamic method is that you do not load the library when the application starts,
and at the moment when you really need it. Judge for yourself, because if the function described
in a dynamic library, used only in 10% of program launches, then absolutely not
it makes sense to use static method downloads. Unloading the library from memory in this case
is also carried out under your control. Another advantage of this method
loading DLLs means reducing (for obvious reasons) the startup time of your application.
What are the disadvantages of this method? The main one, it seems to me, is that the use
this method is more troublesome than the static loading discussed above.
First you need to use Windows function API LoadLibrary.
To obtain a pointer to the exported procedure or function, you must
use the GetProcAddress function. After finishing using the DLL
must be unloaded using FreeLibrary.
Calling procedures and functions loaded from DLLs.
The way procedures and functions are called depends on how you loaded the dynamic library,
in which these subroutines are located.
Calling functions and procedures from statically loaded DLLs is quite simple. Originally in the app
must contain a description of the exported function (procedure). After that you can use them
just as if they were described in one of your application modules.
To import a function or procedure contained in a DLL, you must use
external modifier in their declaration. For example, for the HelloWorld procedure we considered above
The calling application should have the following line:
procedure SayHello(AForm: TForm); external myfirstdll.dll";
Keyword external tells the compiler that this procedure can be found in
dynamic library (in our case - myfirstdll.dll).
The call to this procedure then looks like this:
...
HelloWorld(self);
...
When importing functions and procedures, be especially careful when writing their names and interfaces!
The fact is that during application compilation there is no check for the correctness of object names,
exported from the DLL will not be implemented, and if you incorrectly described any function,
then the exception will be thrown only at the execution stage of the application.
Import from DLL can be carried out by procedure (function) name, sequence number or
with a different name.
In the first case, you simply declare the name of the procedure and the library from which you are importing it
(we looked at this a little higher). Importing by sequence number requires you to specify this very number:
procedure HelloWorld(AForm: TForm); external myfirstdll.dll index 15;
In this case, the name you give to the procedure when importing does not have to be the same as
which was specified for it in the DLL itself. Those. the above entry means,
that you are importing from the dynamic library myfirstdll.dll the procedure that was exported in it
fifteenth, and within your application this procedure is named SayHello.
If for some reason you do not use the import method described above,
but still want to change the name of the imported function (procedure), you can use the third method:
procedure CoolProcedure; external myfirstdll.dll name "DoSomethingReallyCool";
Here, the imported CoolProcedure procedure is named DoSomethingReallyCool.
Calling procedures and functions imported from dynamically loaded libraries
somewhat more complicated than the method we discussed above. In this case, you need to declare
a pointer to the function or procedure you are going to use.
Remember the HelloWorld procedure? Let's see what needs to be done to
to call it to execute in case of dynamic loading of a DLL. First of all, you
it is necessary to declare a type that would describe this procedure:
type
THelloWorld = procedure(AForm: TForm);
Now you must load the dynamic library, using GetProcAddress get
a pointer to a procedure, call this procedure for execution, and finally unload the DLL from memory.
Below is code demonstrating how this can be done:

DLLInstance: THandle ;

HelloWorld:THelloWorld;

begin

(load DLL)

(we get a pointer)

(call the procedure for execution)

HelloWorld(Self) ;

(unload DLL from RAM)

FreeLibrary(DLLInstance) ;

end ;

As mentioned above, one of the disadvantages of statically loading a DLL is the inability to
continuation of application operation in the absence of one or more libraries. In the case of dynamic
By downloading, you have the opportunity to programmatically handle such situations and prevent the program from
fell out" on its own. Based on the values ​​returned by the LoadLibrary and GetProcAddress functions, you can
determine whether the library was loaded successfully and whether it was found in it required by the application procedure.
The code below demonstrates this.

procedure TForm1.DynamicLoadBtnClick (Sender: TObject ) ;

type

THelloWorld = procedure (AForm: TForm);

DLLInstance: THandle ;

HelloWorld:THelloWorld;

begin

DLLInstance:= LoadLibrary("myfirstdll.dll" ) ;

if DLLInstance = 0 then begin

MessageDlg( "Unable to load DLL", mtError, [ mbOK], 0 ) ;

Exit ;

end ;

@HelloWorld:= GetProcAddress(DLLInstance, "HelloWorld" ) ;

if @HelloWorld nil then

HelloWorld (Self)

else

MessageDlg( "The required procedure was not found!.", mtError, [ mbOK], 0 ) ;

FreeLibrary(DLLInstance) ;

end ;

DLLs can store not only code, but also forms.
Moreover, creating and placing forms in a dynamic library is not too much different from working
with forms in a regular project. First we'll look at how a library can be written,
containing forms, and then we'll talk about using MDI technology in a DLL.
I will demonstrate the development of a DLL containing a form using an example.
So, first, let's create new project dynamic library.
To do this, select the File|New menu item, and then double-click on the DLL icon.
After this you will see code similar to the following:

Save the resulting project. Let's call it DllForms.dpr.
Now you need to create a new form. This can be done in different ways.
For example, by selecting the File|New Form menu item. Add some components to the form.
Let's name the form DllForm and save the resulting module under the name DllFormUnit.pas.
Let's return to the main module of the project and place the ShowForm function in it, the task of which will include
creating a form and displaying it on the screen. Use the code below for this.

Form: TDLLForm;

begin

Result:= Form.ShowModal ;

Form.Free ;

end ;

Please note that in order for the project to be compiled without errors, you need to add the Forms module to the uses section.
We export our function using the exports keyword:
exports
ShowForm;
We compile the project and get the dllforms.dll file. These simple steps are everything
what you need to do to note that the ShowForm function is declared using the stdcall keyword.
It signals the compiler to use the convention when exporting a function
by standard call calling convention. Exporting a function this way creates
the ability to use the developed DLL not only in applications created in Delphi.
Calling conventions determine how arguments are passed when calling a function.
There are five main conventions: stdcall, cdecl, pascal, register and safecall.
You can learn more about this by looking at the "Calling Conventions" section in the Delphi help file.
Also note that the value returned by the ShowForm function is
corresponds to the ShowModal value. This way you can transfer some information
about the state of the form to the calling application.
Below are two listings, the first of which contains the complete code for the file
DLL project (the module with the form is not shown here), and the second is the module calling application,
which uses the library we just developed.

libraryDllForms;

uses

DllFormUnit in "DllFormUnit.pas" (DllForm) ;

($R *.RES)

function ShowForm: Integer ; stdcall ;

Form: TDLLForm;

begin

Form:= TDLLForm.Create(Application) ;

Result:= Form.ShowModal ;

Form.Free ;

end ;

begin

end.


unit TestAppUnit;

interface

uses

Windows, Messages, SysUtils, Classes, Graphics,

Controls, Forms, Dialogs, StdCtrls;

type

TForm1 = class(TForm)

Button1: TButton;

procedure Button1Click(Sender: TObject ) ;

private

(Private declarations)

public

(Public declarations)

end ;

Form1: TForm1;

function ShowForm: Integer ; stdcall ;

External "dllforms.dll" ;

implementation

($R *.DFM)

procedure TForm1.Button1Click (Sender: TObject ) ;

begin

end ;

end.

Please note that the stdcall keyword was also used when exporting the function.
Should be paid Special attention for working with child forms in DLLs. If, for example,
in the calling application, the main form has a FormStyle property value equal to MDIForm,
then when you try to call the MDIChild-form from the DLL, an error message appears on the screen,
which will say that there is no active MDI form.
The moment you try to show your child window, VCL checks for correctness
FormStyle properties of the application's main form. However, in our case everything seems to be true.
So what's the deal? The problem is that when performing such a check, the Application object is considered,
belonging not to the calling application, but to the dynamic library itself.
Well, naturally, since the DLL does not have a main form, the check throws an error.
In order to avoid this situation, you need to assign the Application object of the dynamic library
the Application object of the calling application. Naturally, this will only work if
when the calling program is a VCL application. In addition, before unloading the library from memory
it is necessary to return the value of the library's Application object to its original state.
This will allow the memory manager to clean up the RAM occupied by the library.
Therefore, you need to store a pointer to the library's native Application object
in a global variable that can be used to restore its value.
So, let's go back a little and list the steps we need to work with placed
in DLL MDIChild forms.
In the dynamic library we create a global type variable TApplication.
We store a pointer to the Application DLL object in a global variable.
We assign a pointer to Application to the Application object of the dynamic library
calling application.
We create an MDIChild form and work with it.
We return the value of the Application object of the dynamic library to its original state
and unload the DLL from memory.
The first step is simple. We simply place the following code at the top of the DLL module:
var
DllApp:TApplication;
Then we create a procedure that will change the value of the Application object and create a child form.
The procedure might look something like this:

procedure ShowMDIChild(MainApp: TApplication) ;

Child: TMDIChild;

begin

if not Assigned (DllApp) then begin

DllApp:= Application;

Application:= MainApp;

end ;

Child:= TMDIChild.Create(Application.MainForm) ;

Child.Show ;

end ;

All we need to do now is provide the return value of the Application object
to its original state. We do this using the MyDllProc procedure:

procedure MyDLLProc(Reason: Integer ) ;

begin

if Reason = DLL_PROCESS_DETACH then

(DLL is unloaded. Restore the value of the Application pointer)

if Assigned (DllApp) then

Application:= DllApp;

end ;

Instead of a conclusion.
Using dynamic link libraries is not as difficult as it might seem at first glance.

Using dynamic link libraries is not as difficult as it might seem at first glance.
DLLs provide great optimization opportunities application operation,
as well as the work of the programmers themselves. Use DLL and maybe your life will become easier!
http://subscribe.ru/
Email: [email protected] Search
to APORT on Subscribe.Ru



Introduction

Due to the rapid development of programming technologies, more and more people are faced with the problem of increasing the capabilities of their programs. This article is devoted precisely to this issue, namely, DLL programming in Borland Delphi. In addition, since we will touch on issues related to the use of DLLs, we will also touch upon importing functions from foreign DLLs (including system ones, i.e. WinAPI).

DLL Application Areas

So, why are DLLs needed and where are they used?.. Let's list just some of the areas of their application:

Separate libraries Contain additional functions useful for programmers. For example, functions for working with strings, or complex libraries for converting images. Resource storage DLLs can store not only programs and functions, but also all kinds of resources - icons, pictures, string arrays, menus, etc. Support libraries Examples include libraries of such well-known packages as: DirectX, ICQAPI (API for ICQ), OpenGL, etc. Parts of a program For example, program windows (forms), etc. can be stored in a DLL. Plugins This is where the real scope for a programmer's thoughts is! Plugins are additions to a program that expand its capabilities. For example, in this article we will look at the theory of creating a plugin for your own program. A shared resource DLL (Dynamic Link Library) can be used by several programs or processes at once (the so-called sharing - shared resource)

Brief description of functions and techniques for working with DLLs

So, what techniques and functions do you need to use to work with DLLs? Let's look at two methods for importing functions from a library:

1 way. Binding a DLL to a program.

This is the simplest and easiest method for using functions imported from a DLL. However (and this should be noted) this method has a very significant drawback - if the library that the program uses is not found, then the program simply will not start, giving an error and reporting that the DLL resource was not found. And the library will be searched: in the current directory, in the program directory, in the WINDOWS\SYSTEM directory, etc. So, first, the general form of this technique:


FunctionName (or ProcedureName) the name of the function (or procedure) that will be used in your program; Par1, Par2, ... names of function or procedure parameters; Par1Type, Par2Type, ... types of function or procedure parameters (for example, Integer); ReturnType return type (function only); stdcall directive, which must exactly match the one used in the DLL itself; external "DLLNAME.DLL" directive specifying the name of the external DLL from which this function or procedure will be imported (in this case - DLLNAME.DLL); name "FunctionName" ("ProcedureName") directive specifying the exact name of the function in the DLL itself. This is an optional directive that allows a function to be used in a program that has a name other than the true one (which it has in the library); index FunctionIndex(ProcedureIndex) directive specifying serial number functions or procedures in a DLL. This is also an optional directive.

This is a much more complex, but also more elegant method. It does not have the disadvantage of the first method. The only thing that is unpleasant is the amount of code required to implement this technique, and the difficulty is that the function imported from the DLL is accessible only when this DLL is loaded and is in memory... An example can be found below, but for now - short description WinAPI functions used by this method:

LoadLibrary(LibFileName: PChar) Loads the specified library LibFileName into memory. On success, the function returns a handle (THandle) to the DLL in memory. GetProcAddress(Module: THandle; ProcName: PChar) reads the address of the exported library function. On success, the function returns a handle (TFarProc) to the function in the loaded DLL. FreeLibrary(LibModule: THandle) invalidates the LibModule and frees the memory associated with it. It should be noted that after calling this procedure, the functions of this library are no longer available.

Practice and examples

Well, now it’s time to give a couple of examples of using the above methods and techniques:

Example 1. Linking a DLL to a program


Now the same thing, but in the second way - with dynamic loading:


Note:

You should refrain from using the string type in library functions because There are problems with "memory sharing" when using it. You can read more about this (though in English) in the text of the empty DLL project that Delphi creates (File -> New -> DLL). So it's better to use PChar and then convert it to string using StrPas function if necessary.

Well, now let’s look at the DLL itself:

Example 3. Source of the project MYDLL.DPR


Placing resources and forms in DLLs

A DLL can contain not only functions, but also cursors, pictures, icons, menus, text strings. We will not dwell on this. I will only note that to load a resource you need to load the DLL, and then, having received its descriptor, load the resource itself with the appropriate function (LoadIcon, LoadCursor, etc.). In this section, we will only briefly touch on the placement of application windows (i.e. forms in Delphi) in DLLs.

To do this, you need to create a new DLL and add a new form to it (File -> New -> DLL, and then File -> New Form). Next, if the form is a dialog box ( modal form(bsDialog)), then add the following function to the DLL (let’s say the form is called Form1, and its class is TForm1):

Example 4: Placing a form in a DLL


If you need to place a non-modal form in a DLL, then you need to create two functions - opening and closing the form. In this case, you need to force the DLL to remember the handle to this form.

Creating plugins

Here we will not consider plugins in detail, because... The examples already given above will help you easily understand the lion's part of DLL programming. Let me just remind you that a plugin is an addition to the program that expands its capabilities. At the same time, the program itself must provide for the presence of such additions and allow them to fulfill their purpose.

That is, for example, to create a plugin for a graphic editor that would perform image conversion, you need to provide at least two functions in the plugin (and, accordingly, call these functions in the program) - a function that would return the name of the plugin (and /or its type) to add this plugin to the menu (or toolbar), plus main function- image transmission and reception. Those. first the program searches for plugins, then for each found one it calls its identification function with a strictly defined name (for example, GetPluginName) and adds the desired item to the menu, then, if the user has selected this item, it calls the second function, which passes the input image (or file name, containing this image), and this function, in turn, processes the image and returns it in a new form (or a file name with a new image). That's the essence of the plugin... :-)

Epilogue

This article shows the basics of using and creating DLLs in Borland Delphi. If you have questions, send them to me by email:

Dear colleagues!

In this article I will try to answer the questions: What is DLL? What is it for? And how to create and use DLL with help Delphi.

What is DLL?

Dynamic Link Library or for short DLL is a library that contains a set of data or functions for use in other programs.

Areas of use:

  • Storage of resources: icons, sounds, cursors, etc. We save on the size of executable files by combining resources into a single library.
  • Placement of individual program modules and interface forms. We get the opportunity to partially update the application, and with a dynamic connection, it is possible to update modules without restarting the main program.
  • Use as plugins (PlugIn). We provide the opportunity to expand the functionality of the application without rewriting the main program code.
  • The library can be used on different languages programming, regardless of the language in which it was written.

Creating your own DLL.

To create a library, go to the menu File -> Other and choose Delphi Projects -> Dynamic-link Library.
The code text with a template for creating a library will open:

Library Project1; uses System.SysUtils, System.Classes; ($R *.res) begin end.

Resource placement

Let's add an icon to the library, which we will use later in the main program.
How to add resources to a project is described in detail in the article.

Let’s add an “About the program” form.
Click File -> New -> VCL Form. Let's add text and an "OK" button:

Let's add a function that will display the standard MessageBox with a question, buttons “Yes”, “No” and with a result in the form True or False.

Function YesNoDlg(const Question: PChar): boolean; stdcall; begin Result:= (MessageBox(0, Question, "Confirmation", MB_YESNO + MB_ICONQUESTION) = ID_YES); end;

Pay attention to the keyword stdcall. It determines exactly how parameters and results will be passed when calling functions. You can read more on the Calling Agreement wiki page.

We will also add a procedure that will be used as a plugin for the main program. Which will add an “About the program” button to the main program menu to open the window we created.
Procedure code:

Procedure PlugIn(Form: TForm); stdcall; var i: integer; mi: TMenuItem; begin for i:= 0 to Form.ComponentCount - 1 do begin if (Form.Components[i].ClassName = "TMenuItem") and (Form.Components[i].Name = "miHelp") then begin mi:= TMenuItem .Create(Form.Components[i]); mi.Caption:= "About the program"; mi.OnClick:= fmAbout.onAboutButtonClick; TMenuItem(Form.Components[i]).Add(mi); Exit; end; end; end;

The form of the program is passed to the procedure as a parameter. We check whether there is a menu item named “ miHelp"and if the menu is found, then add our button to it.

Now we will indicate which functions and procedures can be used from our library.
Let's add the line:

Exports PlugIn, YesNoDlg;

Let's compile the function Project -> Build or using hotkey Shift+F9.
If there are no errors in the code, then a file with the extension should appear in the project folder DLL.

Now let's move on to creating an application that will use our library.

Let's create a form in the application Main in which we will add a component with the following buttons: Program -> Exit and Help. For the last one, let's set a name - miHelp:

Let's move on to the form code.

Functions from the library DLL can be connected in two ways:
Static— the library is connected when the program starts. If the library or function name is not found, the program will generate an error and will not run.
Dynamic— the library is connected either immediately before a function call or upon a specific event.

Let's consider static way connections:

Type TfmMain = class(TForm) MainMenu: TMainMenu; miProgram: TMenuItem; miExit: TMenuItem; miHelp: TMenuItem; procedure FormCreate(Sender: TObject); procedure miExitClick(Sender: TObject); private public end; procedure PlugIn(Form: TForm); stdcall; external "SampleDLL.dll"; var...

Keyword external indicates that this function is connected from an external library.

For the event onCreate form, add a procedure call PlugIn:

Procedure TfmMain.FormCreate(Sender: TObject); begin PlugIn(Self); end;

As a parameter Form we pass the current form to the procedure (keyword Self).

When starting the program, we should have the “About the program” item in the “Help” section of the main menu.

Let's move on to the dynamic connection method.

We will need three functions WinApi:

LoadLibrary
Loads the library into computer memory. As a result, it returns a pointer to the library in memory. In case of error, it will return 0.

LoadLibrary(lpLibFileName: LPCWSTR): HMODULE;

lpLibFileName— Library file name.

GetProcAddress
Find a function in a library by name. The result will be a function pointer. If the function is not found, it will return nil.

GetProcAddress(hModule: HMODULE; lpProcName: LPCSTR): FARPROC;

hModule
lpProcName— Function name.

FreeLibrary
Unloads the library from the computer's memory. The result will be True in case successful implementation and False in case of error.

FreeLibrary(hLibModule: HMODULE): BOOL;

hLibModule— Pointer to the loaded library.

Now, using the dynamic method, we will get resources, our icon and add a function call to the “Exit” button YesNoDlg to confirm the program is closed.
Add the code to the same onCreate event:

Procedure TfmMain.FormCreate(Sender: TObject); var DLLHandle: THandle; begin PlugIn(Self); DLLHandle:= LoadLibrary("SampleDLL.dll"); if DLLHandle = 0 then raise Exception.Create("Could not include library 'SampleDLL'!"); try Self.Icon.LoadFromResourceName(DLLHandle, "my_icon"); finally FreeLibrary(DLLHandle); end; end;

And for the event onClick menu item "Exit":

Procedure TfmMain.miExitClick(Sender: TObject); var DLLHandle: THandle; Dlg: function(const Question: PChar): boolean; stdcall; begin DLLHandle:= LoadLibrary("SampleDLL.dll"); if DLLHandle = 0 then raise Exception.Create("Could not include library 'SampleDLL'!"); try @Dlg:= GetProcAddress(DLLHandle, "YesNoDlg"); if not Assigned(@Dlg) then raise Exception.Create("The function named "YesNoDlg" was not found in the library "SampleDLL"!"); if Dlg("Exit the program?") then Close; finally FreeLibrary(DLLHandle); end; end;

If you wrote everything correctly, then after starting the program the form icon should change, the “About the program” button should be added, when clicked on it the form will show About and when you press the exit button, the program will ask for confirmation: “Exit the program?”

I hope you find this small example of using the features useful. DLL libraries.
The project sources can be downloaded.

DLL- Dynamic Link Library, or dynamic link library, which allows you to reuse the same functions in different programs. Quite actually convenient tool, especially since once written the library can be used in many programs. In today's lesson we will learn how to work with dll and of course create them!
Well, let's begin!

First, let's create our first Dynamic Link Library! Let's go to Delphi and immediately go to the menu File -> New -> Other.
The following window appears in front of us:

Select Dynamic-Link Library from the list (in versions earlier than 2009 Delphi The item is called DLL Wizard).

As a result, we only have a window with the code; note that we don’t have any form here!
Now the fun begins. Let's write our first procedures in the library.

libraryProject2;
//You probably already noticed that instead of program
//when creating a dll, the word library is used.
//Meaning library.
uses
SysUtils, dialogs,
Classes; // Attention! Don't forget to specify these modules,
// otherwise the code won't work

($R *.res)
(THE DLL CODE IS PLACED IN THIS PART)

Procedure FirstCall; stdcall; export;
//Stdcall - With this operator, parameters are pushed onto the stack
//from right to left, and aligned to the standard value
//Export can, in principle, be omitted, used for clarification
//export a procedure or function.

Begin
ShowMessage(" My first procedure in dll");

End;

Procedure DoubleCall; stdcall; export;
Begin
ShowMessage(" My second procedure");
//Call a message on the screen
End;

Exports FirstCall, DoubleCall;
//Exports contains a list of exported elements.
//Which will later be imported by some program.

begin
End.

We will stop here for now because... for a simple example this will be quite enough. Now we save our project, I personally saved it under the name Project2.dll and press the key combination CTRL+F9 to compile the library. In the folder where you saved the dpr file, a file with the dll extension will appear, this is our just created library. I have it called Project2.dll

Let's now start calling procedures from this library. We create according to standard scheme new application. Before us is nothing unusual, just a form. Save the new application to some folder. And copy the newly created one into the same folder dll library. Those. V in this example Project2.dll

Now you have to choose how to call functions from the library. There are two calling methods in total.

Method No. 1
Perhaps this is the simplest method of calling procedures located in the library.
Ideal for working with only one library.

Here we go...
After the implementation keyword, write the following code:

Procedure FirstCall; stdcall; external "Project2.dll" ;
// Instead of Project2.dll there can be any library name

Procedure DoubleCall; stdcall; external "Project2.dll" ;

Here, as you probably already guessed, we tell the program the names of our procedures and say that they are in dll library, in my case named Project2.dll

Now, in order to call these procedures, we only need to insert their names anywhere in the code, which we will do now. Drop 2 Button components from the Standard tab onto the form and create an OnClick event handler on each

OnClick of the first button:


Begin
FirstCall;
End;

OnClick of the second button:


Begin
DoubleCall; // Name of the procedure that is in the dll
End;

That's all!

Method number 2:
More complex than the first one, but it has its advantages, and most importantly, it is ideal for plugins.
To apply this method, first of all we declare several global variables:

Var
LibHandle: HModule; //Link to the library module
FirstCall:procedure; stdcall;
//Names of our procedures located in the library.

DoubleCall: procedure; stdcall;

Then, after the implementation keyword, we will write a procedure that will load our library:

Procedure LoadMyLibrary(FileName: String);
Begin
LibHandle:= LoadLibrary(PWideChar(FileName));
//Loading the library!
// Attention! PChar for versions below 2009 Delphi
If LibHandle = 0 then begin
MessageBox(0,"",0,0);
Exit;
End;
FirstCall:= GetProcAddress(LibHandle,"FirstCall ");
//Get a pointer to the object
//1st parameter link to library module
//2nd parameter object name in dll

DoubleCall:= GetProcAddress(LibHandle,"DoubleCall");
If @FirstCall = nil then begin

MessageBox(0," Unable to load library",0,0);
Exit;
End;
If @DoubleCall = nil then begin
//Check for the presence of this function in the library.
MessageBox(0," Unable to load library",0,0);
Exit;
End; End;

Then on the form we create an OnCreate event handler, in which, using the just created procedure, we will load our library

Procedure TForm1.FormCreate(Sender: TObject);
Begin
LoadMyLibrary("Project2.dll ");
End;

Now, again, in order to call the necessary procedures from our library, we only need to insert their names anywhere in the code. To do this, drop 2 Button components from the Standard tab onto the form and create an OnClick event handler on each

OnClick of the first button:

Procedure TForm1.Button1Click(Sender: TObject);
Begin
FirstCall; // Name of the procedure that is in the dll
End;

OnClick of the second button:

Procedure TForm1.Button2Click(Sender: TObject);
Begin
DoubleCall; // Name of the procedure that is in the dll
End;

And finally, we create an OnDestroy event handler on the form, in which we unload dll library from memory

Procedure TForm1.FormDestroy(Sender: TObject);
Begin
FreeLibrary(LibHandle);
//Unload the library from memory.
End;

That's all! The second method turned out to be quite cumbersome, but its advantage is to clarify the object stored in the library.

P.S. Do you want to receive ahead of all other site visitors? Fresh Videos lessons, audio podcasts, articles on Delphi.
Participate in competitions and gradually join our team?!
Then right now subscribe to the site's free multimedia newsletter
We are already more than 3500 people!

Modular programs

When developing programs, it often turns out that different software applications require the same objects, their properties, methods, procedures and functions. For example, almost all programs display information on the screen and use standard objects Windows interface(windows, buttons, menus...) It would be in highest degree It is unreasonable to cram the rendering code for each such element into all programs.

Thus, the problem of separation arises big program into separate independent modules, each of which contains a specific set of procedures and functions. The procedures and functions of such a module can be called by any other program. Such modules are called dynamic link libraries(DLL – dynamically linked library, Fig. 19.1). The word "dynamic" indicates that the library is included not at the compilation stage, but after the program is launched.

Rice. 23.1 DLLs - libraries.

DLL libraries are widely used in most programs. Let's say that the Windows operating system itself includes several hundred DLLs, and the functionality contained in them can be used by our programs to avoid reinventing the wheel again.

When should DLLs be used? First, if you are developing several independent programs and they use the same fragments program code. Then such fragments should be taken to the library. This not only saves disk space, but also makes it easier to make changes to the project - you only have to edit one DLL, and not many exe programs. Secondly, if you want to give users of your brilliant program the opportunity to use it in their developments. In this case, the program is usually divided into a small exe file and a large DLL library. Other developers will be able to use your DLL as long as you provide a description of the procedures and functions it contains and their parameters. It is commonly said that the procedures and functions of a DLL exported to other programs.

In the environment Delphi programming there are built-in tools for quick creation DLL libraries. To be specific, let's create a library containing the function GetArea(a, b, c: REAL):REAL. This function takes as input the lengths of the sides of the triangle. The function returns the area of ​​the given triangle:

FUNCTION GetArea(a, b, c:REAL):REAL;

Result:=SQRT(p*(p-a)*(p-b)*(p-c))

We launch Delphi, and then we act unconventionally. Select the menu items File à New à Other, in the window that opens, on the New tab, click on the DLL Wizard icon. This creates a template DLL file. It is very similar to a regular Delphi unit, but it starts with a Library statement. Save the project under the name that the DLL will receive in the future, say GetA. The name GetArea cannot be used - it is already taken by the function name.

Now, after the USES operator, we write the text of our function, but with some changes in the header:

FUNCTION GetArea(a, b, c:REAL):REAL; export; stdcall;

The EXPORT keyword indicates that the function is exportable and will be visible from external programs. The word STDCALL (standard call - standard call model) indicates the protocol used for passing parameters to the function. The standard calling model is compatible with programs written in other languages, in particular C, so our DLL can also be used by C programmers.

After the text of the function we will add

The EXPORTS statement lists all procedures and functions exported from the library. This is a kind of catalog of our library.

It is impossible to run the library; it can only be compiled. To do this, select the Project à Build menu item. If everything was done correctly, a file named geta.dll will be created on the disk in the current directory. This is our library.

Important Note : There is a certain subtlety when passing parameters of the STRING type to procedures and functions located in the library. In order to be able to pass parameters of the STRING type, you will have to specify the connection of the ShareMem module in the USES statements of both the library and the program that calls it, and even so that this module is first in the list. Moreover, along with the library you will have to include the file borlndmm.dll (it is included in the Delphi distribution). Avoiding such hassle is very simple: for text type parameters, you should use the ShortString (essentially a regular string, but up to 255 characters long) and PChar (pointer to a text string) data types.







2024 gtavrl.ru.