It is easier to call a DLL than to write a DLL. The first is to introduce the static call method, the dynamic call method will be introduced later, and a comparison of the two methods. Again, let's start with an example of a static call.
Unit Unit1;
Interface
Uses
Windows, Messages, Sysutils, Classes, Graphics,
Controls, Forms, Dialogs, Stdctrls;
Type
TForm1 = Class (Tform)
Edit1:tedit;
Button1:tbutton;
Procedure Button1Click (Sender:tobject);
Private
{Private declarations}
Public
{Public declarations}
End
Var
Form1:tform1;
Implementation
{$R *. DFM}
Our code below is the code we actually write.
function Testdll (I:integer): Integer;stdcall;
External ' Delphi.dll ';
Procedure Tform1.button1click (Sender:tobject);
Begin
Edit1.text:=inttostr (Testdll (1));
End
End.
In the example above we put an edit box and a button on the form, and we wrote very little code to test the Delphi.dll we just wrote. As you can see, the only work we do is to place the description of the Testdll function in implementation and specify the location of the Delphi.dll with the external statement. (In this case, the calling program and the Delphi.dll are in the same directory.) It is exciting that the Testdll function we wrote ourselves was soon recognized by Delphi. You can do an experiment like this: Enter "Testdll", and soon Delphi will use the fly-by cue bar to prompt you for what parameters you should enter, just as simple as the other functions defined in Delphi.
Here are some things to note:
First, call the parameters with StdCall.
As mentioned earlier, the stdcall parameter is used when referencing the functions and procedures in the DLL for the same reason as mentioned earlier.
Second, use the external statement to specify the path and name of the DLL file being called.
As you can see, we specify the name of the DLL file to be called in the external statement. There is no write path because the DLL file is in the same directory as the main program that called it. If the DLL file is in C: \, then we can write the above reference statement as external ' C:\Delphi.dll '. Note the file suffix. dll must be written on.
Third, the global variable cannot be called from the DLL.
If we declare a global variable in the DLL, such as: Var s:byte. In this case, the s global variable in the DLL can be used normally, but s cannot be used by the calling program, and S cannot be passed as a global variable to the calling program. However, variables declared in the calling program can be passed as arguments to the DLL.
The called DLL must be present.
This is important when using a static calling method requires that the DLL file being called and the function or procedure to be called must exist. If there is no or the specified path and file name is incorrect, a run-time error such as "Error launching Program" or "*.dll File not found" is prompted when you run the main program.
Writing skills
1, in order to ensure the correctness of the DLL, can be written into a common part of the application, debugging and error after the separation from the main program, compiled into a DLL.
2, in order to ensure the universality of the DLL, should be in their own DLL to prevent the name of the visual control, such as: Edit1.text in the Edit1 name, or custom non-Windows defined type, such as a record.
3, for easy debugging, each function and process should be as short as possible, and with specific detailed comments.
4. Use try-finally to handle possible errors and anomalies, and note that you should refer to the Sysutils unit.
5. Use as few references as possible to reduce the size of the DLL, especially if you do not reference a visualization unit, such as a dialogs unit. In general, for example, we can not reference the classes unit, which reduces the compiled DLL by approximately 16Kb.
Call tricks
1. When using a static method, you can rename the called function or procedure. In the previously mentioned DLL example written in C + +, if you remove the extern "C" statement, C + + will compile some strange function names, the original TESTC function will be named @testc$s and so on ridiculous strange name, this is because C + + uses the C + + name mangling technology. This function name is illegal in Delphi, so we can solve this problem:
Overwrite the reference function as
function TESTC (I:integer): Integer;stdcall;
External ' Cpp.dll '; name ' @TestC $s ';
Where name is the function of renaming.
2. You can put the DLLs we write into the Windows directory or the Windows\System directory. This allows you to write only the name of the DLL in the external statement or in the LoadLibrary statement without writing the path. But this is a bit inappropriate, these two directories have a large number of important system DLLs, if you make a DLL with their name, the consequences of this is unthinkable, and your programming technology is not enough to put your own DLL into the system directory of the point!
Debugging Tips
1, we know that DLLs are not to be run and single-step debugging when writing. One way to do this is to set up a host program in the Run|parameters menu. The name of the host program is added to the host application column on the local page for single-step debugging, breakpoint observation, and operation.
2. Add the version information of the DLL. The prologue mentions that version information is important for DLLs, and if the version information is included, the size of the DLL increases by 2KB. It is worthwhile to add such a little space. Unfortunately, if we use the Project|options menu in the version option is not possible, this is not mentioned in the Delphi help file, after the author found that as long as the addition of a line of code on it. The following example:
Library Delphi;
Uses
Sysutils,
Classes;
{$R *. RES}
Note that this line of code must be added to this position
function Testdll (I:integer): Integer;stdcall;
Begin
Result:=i;
End
Exports
Testdll;
Begin
End.
3, in order to avoid the same name as other DLLs, in the DLL to write their own names when it is best to use a combination of character numbers and underscores. such as: Jl_try16.dll.
4, if you originally in Delphi 1 or Delphi 2 has compiled some DLLs, you originally compiled DLL is 16-bit. As long as the source code is recompiled in the new Delphi 3 or Delphi 4 environment, you can get a 32-bit DLL.
Reference article: Implement function and object sharing between Delphi and C + + http://www.zahui.com/html/2/4202.htm
1.c++ sharing Delphi Objects
To implement invoking a Delphi object from C + +, first describe the interface of the object that needs to be shared in the interface portion of the Delphi unit and the header file of C + +, define what properties and methods the object contains in the object interface, and describe the parts that are available for sharing. Sharing of objects is the key to the sharing of methods. In the Delphi language, to make an object can be shared, it can be described as two interface parts, temporarily known as "shared interface" and "Implementation interface." Where the shared interface indicates which methods in an object are shared by another language, the implementation interface inherits the shared interface, and in the unit implementation part defines the implementation for the method in the implementation interface. To define a Delphi object that can be shared by C + +, the description of the shared interface should be noted:
In the Delphi program, the method to be shared must be described as abstract and virtual.
In C + + programs, you must use the keyword "virtual" and "= 0" suffix, the method of sharing from Delphi as "pure virtual";
The shared object method must be described in both languages as the same invocation method, typically using the standard system invocation method (stdcall).
The following are examples of these rules, assuming that there is one such Delphi object:
Ttestobject=class
Procedure Proc1 (X:integer);
function Func1 (x:integer):P char;
Procedure Proc2;
function Func2:integer;
End
If the C + + program needs to share the methods Proc1, FUNC1, the above instructions can be modified to the following form:
Stestobject=class
Procedure Proc1 (X:integer); Virtual Abstract stdcall;
function Func1 (X:integer); Virtual Abstract stdcall;
End
Ttestobject=class (Stestobject)
Procedure Proc1 (X:integer);
Fuction Func1 (X:integer):P char;
Procedure Proc2;
Fuction Func2:integer;
End
In a C + + program, do the following object prototype description:
Class Stestobject {
virtual void Proc1 (int x) = 0;
Virtual char *func1 (int x) = 0;
};
In order to successfully access the Delphi-defined class in C + +, the Delphi interface specification must contain a shareable "manufacturing function" createtestobject, which can be defined in a dynamic-link library or a target file (. Factory). OBJ), for example:
Library TestLib;
Exports createtestobject;
function Createtestobject:stestobject; stdcall;
Begin
Result:=ttestobject.create;
End
...
End.
With this processing, the Delphi-defined object can now be used in a C + + program in the following way:
extern "C" Stestobject stdcall *createtestobject ();
void Usetestobject (void) {
Stestobject *thetestobject=createtestobject ();
Thetestobject->proc1 (10);
Char *str=thetestobject->func1 (0);
}
When calling the manufacturing function Createtestobject, actually already occupies the space of an object instance on the Delphi side, the C + + program must consider releasing this space after all processing for the object, the concrete implementation can define a class in Delphi, This is accomplished by using the shared method of the Proc1 above:
Stestobject=class
Procedure Proc1 (X:integer); Virtual Abstract stdcall;
function Func1 (X:integer); Virtual Abstract stdcall;
Procedure free; Virtual Abstract stdcall;
End
...
Implementation
...
Procedure Ttestobject.free;
Begin
...
End
...
End.
2.Delphi shared C + + objects
Typically, programmers will consider using Delphi to compile the user interface, so Delphi code calls C + + code seems more practical. In fact, the implementation of Delphi shared C + + objects is very similar to the above C + + shared Delphi objects. Define C + + classes with the same shared interface and implementation of the interface description method:
Class Stestobjedt {
virtual void Proc1 (int x) = 0;
Virtual char *func1 (int x) = 0;
};
Class Ttestobjedt:p ublic stestobject {
void Proc1 (int x);
char *func1 (int x);
void Proc2 ();
int Func2 ();
void free ();
};
Then implement these methods. Similarly, a C + + object requires a corresponding manufacturing function, where the DLL is the example
Stestobject stdcall Export *createtestobject () {
Return (Stestobject *) New Ttestobject.create;
}
Delphi code can easily create an instance in C + + by calling the Manufacturing function createtestobject, get a pointer value to that instance, and invoke the shared method in the object with this pointer value. Of course, don't forget to call free when you're done with the object.
Zhang Wei
Absrtact: Delphi, with its unique control-oriented development approach, powerful database capabilities, and fast compilation techniques, makes it particularly noticeable since its release. With Delphi 5 providing Rich Internet applications, Delphi is becoming one of the most important software development tools, attracting many programmers from the original visual Basic, Foxpro, dBASE, and even C + +. One of the key issues that these programmers need to solve when using Delphi is how to use their original code. This article describes how Delphi integrates with C + + programs, including:
The function sharing between Delphi and C + +;
Static link and dynamic link of code;
The share of the object.
Sharing of functions
Calling the C + + function in Delphi is quite straightforward with C + + calling Delphi functions, it is important to note that the default method of Delphi 1 is Pascal, the default Way of Delphi 4, Delphi 5 is to optimize the cdecl call mode, That is, register mode. To implement function sharing between C + + and Delphi programs, you should use the standard system call mode, stdcall, unless there are sufficient reasons. In order for the C + + compiler to not mark a function as "Mang led", the Delphi compiler mistakenly considers the function to be a cdecl invocation, and should be shared with extern "C" in C + + code, as shown in the following example:
Prototype Description:
In C + +:
extern "C" int _stdcall TestFunc ();
In Delphi:
function Testfunc:integer; stdcall;
Call Syntax:
In C + +:
int I=testfunc ();
In Delphi:
var I:integer;
...
Begin
...
I:=testfunc;
...
End
Parameters for shared functions must be variable classes supported in both languages
Reference article: Use of dynamic link libraries in DELPHI http://blog.csdn.net/feifei1018/admin/EditPosts.aspx
In Delphi, there are two ways to invoke a process that is stored in a DLL (a dynamic-link library).
First, call the method
1. Static calls or explicit mounts use an external declaration clause that causes the DLL to be loaded before the application starts executing. For example:
Function instring (Sourcestr:pchar;
Check:char): integer; Far External ' demostr '
This method lists the routines to be called from the DLL in the interface section of the cell, using the external indicator word. The FAR directive indicates subroutines that can be called by other segments, such as other units. All subroutines declared in the cell interface are by default the far type, and the opposite instruction is near.
If you do not follow anything after external, you must specify a DLL name with the {$ L} compilation instruction, such as:
{$ L Mydlls.dll}
Procedure SetString (var str:string);
stdcall; External
However, when using a static call method, the program cannot determine the DLL's invocation during run time. When using a DLL in Delphi, the identifier of the routine must be exactly the same as the identifier of the corresponding output routine in the DLL (although the Delphi itself is not case sensitive).
2. Dynamic call or implicit loading
Using the Windows API functions Loadlibrary and GetProcAddress can implement dynamic load DLLs during runtime and invoke the procedures in them.
For example:
Type tmyproc=procedure (Param:pchar); stdcall;
Var Myproc:tmyproc;
Myhandle:thandle;
Myhandle:=loadlibrary (' Mydll ');
If myhandle< =0 Then
Raise exception.create
(' Dynamic link library call failed, error code
Yes: ' +inttostr (GetLastError))
Else
@MyProc: =getprocaddress (myhandle, ' demoproc ');
If not Assigned (MyProc) Then
Raise exception.create (' GetProcAddress
Call failed with error code
Yes: ' +inttostr (GetLastError))
Else MyProc (Pchar (' A string '));
FreeLibrary (Myhandle); Uninstalling DLLs
Second, the mode of invocation
1, through the process, the name of the letter;
2, through the process, function aliases;
3, through the process, the sequence number of the function
Example: Function getstring:string; stdcall; The external ' Mydlls.dll ' name ' MYGETSTR ' name clause specifies that the function name Getstring be changed to Mygetstr, and when the program calls this routine, the name mygetstr is used; Function Getstring: string; stdcall; External ' Mydlls.dll ' Index 5 INDEX clause introducing a routine by index number can reduce the load time of the DLL.
Iii. calling convention
The calling convention refers to the order in which parameters are passed when the routine is called. The calling conventions supported by DLLs in Delphi are:
calling convention parameter Pass Order
Register from left to right
Pascal from left to right
StdCall from right to left
Cdecl from right to left
Safecall from right to left
Using the StdCall method, can guarantee the compatibility of DLLs written in different languages, and it is also the contract way of Windows API; Delphi 3. 0, 4. The default invocation of 0 is register; cdecl is a calling convention for C/s + +, for DLLs that are written by the C + + language; Safecall is a method that is appropriate for declaring OLE objects.
Iv. variables and segments in DLLs
Any variable declared by a DLL is private, and the module that invokes it cannot directly use the variable it defines. You have to use a procedure or a function interface to do this, and for a DLL, it never has a chance to use the declared variable in the module that called it. A DLL does not have its own SS (stack segment), it uses the stack of applications that call it. Therefore, the procedures and functions in the DLL do not assume Ds=ss (DS is a data segment).
Statically calling DLL in Delphi referencing external DLL External DLL import DLL