⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ch19.htm

📁 delphi自学的好教材!特别适合刚刚起步学习delphi的人员!同样对使用者具有参考价值!
💻 HTM
📖 第 1 页 / 共 5 页
字号:
drain on the system.</P><P><H2><A NAME="Heading5"></A>Anatomy of a DLL Unit</H2><P>As with any other Pascal unit, a DLL unit follows a particular format. Listing19.1 shows a minimal DLL unit.</P><P><H4>LISTING 19.1. A BASIC DLL UNIT.</H4><PRE>library TestDLL;uses  SysUtils,  Classes,  Forms,  Windows;procedure SayHello(AForm : TForm);begin  MessageBox(AForm.Handle, `Hello From a DLL!',    `DLL Message Box', MB_OK or MB_ICONEXCLAMATION);end;exports  SayHello;beginend.</PRE><P>First notice the library keyword at the top of the unit. The library keyword identifiesthis unit as a DLL unit. This DLL has a single procedure called SayHello. The SayHelloprocedure is no different than any other Object Pascal procedure.</P><P>Now turn your attention to the exports keyword near the bottom of the unit. Anyprocedure or function identifiers in the exports section are exported from the DLL.In this case the SayHello procedure is exported. Exporting functions and proceduresis discussed in detail in the section &quot;The exports Keyword.&quot;</P><P>Finally, at the end of the DLL unit you see begin and end keywords. This codeblock is the DLL's main code block and is where you put any code that your DLL needsto execute when the DLL initially loads. In many cases (as in this example), youdon't need any initialization code at all, so this code block is empty.</P><P><H2><A NAME="Heading6"></A>The Basics of DLL Writing</H2><P>Writing a DLL is not difficult. There are a couple of points to be aware of, butmost of it is straight Object Pascal programming. Let's start with a discussion onthe basics of writing DLLs. After that, you can build your first DLL.</P><P><H3><A NAME="Heading7"></A>Functions and Procedures in DLLs</H3><P>Functions and procedures in a DLL fall into two basic categories:</P><UL>	<LI>Functions and procedures local to the DLL	<P>	<LI>Functions and procedures exported from the DLL</UL><P>A DLL might also contain classes that could, of course, have methods. I'm notgoing to talk about methods of a class contained in a DLL at this time, but I'lldiscuss the other two types of functions and procedures next.</P><P><H4>Functions and Procedures Local to the DLL</H4><P>Functions and procedures called within a DLL require no special handling. Youdeclare this type of function or procedure just as you do any function or procedure.The function or procedure can be called by other functions within the DLL, but itcan't be called from outside the DLL. In other words, a calling application willnot have access to these functions and procedures. They can be considered privateto the DLL, much as private methods of a class are private to the class in whichthey reside. In effect, a calling application won't be able to &quot;see&quot; thefunctions and procedures to even know they exist.</P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> In addition to functions and procedures, a DLL can contain global	data that all procedures in the DLL can access. In 16-bit Windows, global data in	a DLL is shared among all instances of the DLL. In other words, if one program changed	the global variable x to 100, x would have the value 100 for all other applications	using the DLL as well. In 32-bit Windows, this is not the case. In 32-bit Windows,	a separate copy of a DLL's global data is created for each process that attaches	to the DLL. <HR></BLOCKQUOTE><H4>Functions and Procedures Exported from the DLL</H4><P>Another category of functions and procedures comprises those that can be calledfrom outside the DLL. These are functions and procedures that are made public by<I>exporting</I> them from the DLL. They can be called by other functions and proceduresin the DLL or by applications outside the DLL.</P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> Functions and procedures in a DLL can be called by executable applications	and also by other DLLs. In other words, one DLL can call functions and procedures	in another DLL. <HR></BLOCKQUOTE><P>After a function or procedure has been exported, you call it from your application.</P><P><H2><A NAME="Heading8"></A>The exports Keyword</H2><P>To export a function or procedure, you use the exports keyword in the DLL. Referto Listing 19.1 for an example of a DLL that exports a procedure called SayHello.Because the SayHello procedure is exported, it can be called from any Delphi application.</P><P><H4>Exporting by Name</H4><P>The most common way of exporting functions and procedures is by name--for example,</P><P><PRE>exports  SayHello,  DoSomething,  DoSomethingReallyCool;</PRE><P>These procedures are exported by their identifier name. You might have noticedthat the exports section has the same syntax as a uses list. Each identifier to beexported is listed, separated by a comma. A semicolon follows the last identifierin the list.</P><P><H4>Exporting by Ordinal Value</H4><P>You can also export procedures and functions by ordinal value. Procedures andfunctions are exported by ordinal value by implementing the index keyword like this:</P><P><PRE>exports  SayHello index 1,  DoSomething index 2,  DoSomethingReallyCool index 3;</PRE><P>When you import the function in the calling application, you specify the ordinalnumber (I'll discuss importing functions and procedures later in the section, &quot;CallingUsing Static Loading&quot;). Most of the time you will export functions and proceduresby name and won't bother with exporting by ordinal.</P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> Delphi automatically assigns an ordinal value to every exported function	and procedure regardless of whether you specify an index number. Specifying an index	number lets you control the ordinal value of the exported function or procedure.	<HR></BLOCKQUOTE><P>Exporting a function or procedure is only half the story. When you build the applicationthat calls the function or procedure, you must <I>import</I> the functions and proceduresyou want to call from the DLL. I'll talk about importing functions and procedureslater in the section &quot;Calling Functions and Procedures in DLLs.&quot;</P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> The global variable HInstance, when used in a DLL, will contain the	instance handle of the DLL. <HR><BR>	<HR>To find out whether your code is executing in a DLL or in an application, check the	value of the global variable IsLibrary. IsLibrary is True when called from a DLL	and False when called from an application.<BR>	<strong>TIP:</strong> If you are having trouble exporting functions or procedures, run the	TDUMP utility on the DLL. TDUMP produces information containing a section on symbols	exported from the DLL. Examining that section will give you a better idea of where	the problem lies. To see just the exported symbols, run TDUMP with the --ee switch--for	example,</P>	<PRE>tdump --ee mydll.dll</PRE></BLOCKQUOTE><PRE></PRE><BLOCKQUOTE>	<P>Remember, you can redirect the output of a command-line application to a text	file with the &gt; symbol:</P>	<PRE>tdump --ee mydll.dll &gt; dump.txt</PRE>	<P><HR></BLOCKQUOTE><PRE></PRE><H3><A NAME="Heading9"></A>Using a DLLProc</H3><P>As I mentioned earlier, any initialization code that the DLL needs to executecan be done in the DLL's main code block. That's easy enough, but what about finalizationcode? DLLs don't have initialization and finalization sections as other units do.You might dynamically allocate memory in the DLL's main code block, but where doyou free it? The answer is a DLLProc. A DLLProc is a procedure that is called atcertain times during the life of a DLL. I'll explain how to use a DLLProc in justa bit, but first let me tell you why DLLProc exists.</P><P>A DLL receives messages from Windows when it is loaded into memory and just beforeit is unloaded from memory. It also receives messages when a process attaches toor detaches from an already-loaded DLL (as in the case of several applications allusing the same DLL). To get these messages, you create a procedure with a specificsignature and assign the address of that procedure to the global variable DLLProc.A typical DLLProc procedure might look like this:</P><P><PRE>procedure MyDLLProc(Reason: Integer);begin  if Reason = DLL_PROCESS_DETACH then    { DLL is unloading. Cleanup code here. }end;</PRE><P>Just declaring a DLLProc procedure is not enough to ensure that the DLLProc willbe used. You must also assign the address of the procedure to the DLLProc globalvariable. You do that in the DLL's main code block. For example:</P><P><PRE>begin  DLLProc := @MyDLLProc;  { More initialization code. }end.</PRE><P>This code will be executed as soon as the DLL loads. The DLLProc is now installedand will be called automatically as processes attach and detach from the DLL or whenthe DLL unloads. Listing 19.2 shows the source code for a DLL that implements a DLLProc.</P><P><H4>LISTING 19.2. A DLL UNIT THAT USES A DLLProc.</H4><PRE>library TestDLL;uses</PRE><PRE>  SysUtils,</PRE><PRE>  Classes,  Forms,  Windows;var  SomeBuffer : Pointer;procedure MyDLLProc(Reason: Integer);begin  if Reason = DLL_PROCESS_DETACH then    { DLL is unloading. Cleanup code here. }    FreeMem(SomeBuffer);end;procedure SayHello(AForm : TForm);begin  MessageBox(AForm.Handle, `Hello From a DLL!',    `DLL Message Box', MB_OK or MB_ICONEXCLAMATION);end;{ More DLL code here that uses SomeBuffer. }exports  SayHello;begin  { Assign our DLLProc to the DLLProc global variable. }  DLLProc := @MyDLLProc;  SomeBuffer := AllocMem(1024);end.</PRE><P>As you might have surmised from Listing 19.2, the Reason parameter of the DLLProcprocedure contains a value representing the reason that the DLLProc is being called.Table 19.1 lists the possible values of the Reason parameter.</P><P><H4>TABLE 19.1. DLLProc Reason VALUES.</H4><P><TABLE BORDER="1">	<TR ALIGN="LEFT" VALIGN="TOP">		<TD ALIGN="LEFT"><I>Value</I></TD>		<TD ALIGN="LEFT"><I>Description</I></TD>	</TR>	<TR ALIGN="LEFT" VALIGN="TOP">		<TD ALIGN="LEFT">DLL_PROCESS_DETACH</TD>		<TD ALIGN="LEFT">The DLL is about to unload from memory.</TD>	</TR>	<TR ALIGN="LEFT" VALIGN="TOP">		<TD ALIGN="LEFT">DLL_THREAD_ATTACH</TD>		<TD ALIGN="LEFT">A process is attaching to the DLL.</TD>	</TR>	<TR ALIGN="LEFT" VALIGN="TOP">		<TD ALIGN="LEFT">DLL_THREAD_DETACH</TD>		<TD ALIGN="LEFT">A process is detaching from the DLL.</TD>	</TR></TABLE></P><BLOCKQUOTE>	<P><HR><strong>NOTE:</strong> Earlier in this section I said that a DLL will receive a message	from Windows when the DLL is initially loaded into memory. It is reasonable to expect	that when a DLL loads, the DLLProc is called with a Reason parameter equal to DLL_PROCESS_ATTACH.	That doesn't happen, however. Windows defines a DLL_PROCESS_ATTACH message, but Object	Pascal does not pass it on to the DLLProc. Instead, Object Pascal calls the DLL's	main code block when the DLL_PROCESS_ATTACH message is received. Because the main	block is called when DLL_PROCESS_ATTACH is received, it is not necessary for Object	Pascal to pass that message on to the DLLProc. <HR></BLOCKQUOTE><P>The DLL_PROCESS_DETACH message is received only once, just before the DLL unloadsfrom memory. (The DLL_THREAD_ATTACH and DLL_THREAD_DETACH messages might be receivedmany times if a DLL is used by several processes. Processes can include applications,multiple threads in a single application, or other DLLs.) You can use a DLLProc,then, to perform any cleanup code required for the DLL.</P><P><H2><A NAME="Heading10"></A>Loading DLLs</H2><P>Before you use a function or procedure in a DLL, you first have to load the DLLinto memory. Loading DLLs at runtime can be accomplished in two ways, as follows:</P><UL>	<LI>Static loading	<P>	<LI>Dynamic loading</UL><P>Both methods have their advantages and disadvantages. I'll explain the differencesbetween static loading and dynamic loading next.</P><P><H3><A NAME="Heading11"></A>Static Loading</H3><P><I>Static loading</I> means that your DLL is automatically loaded when the applicationthat calls the DLL is executed. To use static loading, you declare a function orprocedure that resides in the DLL with the external keyword (more on that in thesection &quot;Calling Using Static Loading&quot;). The DLL is automatically loadedwhen the application loads, and you call any functions or procedures exported fromthe DLL just as you would any other function or procedure. This is by far the easiestway to use code contained in a DLL. The disadvantage to this approach is that ifa DLL that the program references is missing, the program will refuse to load.</P><P><H3><A NAME="Heading12"></A>Dynamic Loading</H3><P><I>Dynamic loading</I> means that you specifically load the DLL when needed andunload it when you are done with it. This type of DLL loading has its advantagesand disadvantages, too. One advantage is that the DLL is in memory only as long as

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -