📄 ch17.htm
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html;CHARSET=iso-8859-1">
<SCRIPT LANGUAGE="JavaScript">
<!--
function popUp(pPage) {
var fullURL = document.location;
var textURL = fullURL.toString();
var URLlen = textURL.length;
var lenMinusPage = textURL.lastIndexOf("/");
lenMinusPage += 1;
var fullPath = textURL.substring(0,lenMinusPage);
popUpWin = window.open('','popWin','resizable=yes,scrollbars=no,width=525,height=394');
figDoc= popUpWin.document;
zhtm= '<HTML><HEAD><TITLE>' + pPage + '</TITLE>';
zhtm += '</head>';
zhtm += '<BODY bgcolor="#FFFFFF">';
zhtm += '<IMG SRC="' + fullPath + pPage + '">';
zhtm += '<P><B>' + pPage + '</B>';
zhtm += '</BODY></HTML>';
window.popUpWin.document.write(zhtm);
window.popUpWin.document.close();
// Johnny Jackson 4/28/98
}
//-->
</SCRIPT>
<!--<link rel="stylesheet" href="../../../../includes/stylesheets/ebooks.css">-->
<META NAME="GENERATOR" Content="Symantec Visual Page Mac 1.1.1">
<TITLE>Teach Yourself Visual C++ 6 in 21 Days -- Ch 17 -- Sharing Your Functionality with Other Applications--Creating DLLs</TITLE>
</HEAD>
<BODY TEXT="#000000" BGCOLOR="#FFFFFF">
<H1 ALIGN="CENTER"><IMG SRC="../button/sams.gif" WIDTH="171" HEIGHT="66" ALIGN="BOTTOM"
BORDER="0"><BR>
Teach Yourself Visual C++ 6 in 21 Days</H1>
<CENTER>
<P><A HREF="../ch16/ch16.htm"><IMG SRC="../button/previous.gif" WIDTH="128" HEIGHT="28"
ALIGN="BOTTOM" ALT="Previous chapter" BORDER="0"></A><A HREF="../ch18/ch18.htm"><IMG
SRC="../button/next.gif" WIDTH="128" HEIGHT="28" ALIGN="BOTTOM" ALT="Next chapter"
BORDER="0"></A><A HREF="../index.htm"><IMG SRC="../button/contents.gif" WIDTH="128"
HEIGHT="28" ALIGN="BOTTOM" ALT="Contents" BORDER="0"></A>
<HR>
</CENTER>
<H1 ALIGN="CENTER">- 17 -<BR>
Sharing Your Functionality with Other Applications--Creating DLLs</H1>
<H1></H1>
<UL>
<LI><A HREF="#Heading1">Why Create DLLs?</A>
<UL>
<LI><A HREF="#Heading2">Creating and Using DLLs</A>
<LI><A HREF="#Heading3">Designing DLLs</A>
</UL>
<LI><A HREF="#Heading4">Creating and Using an MFC Extension DLL</A>
<UL>
<LI><A HREF="#Heading5">Creating the MFC Extension DLL</A>
<LI><A HREF="#Heading6">Adapting the Test Application</A>
<LI><A HREF="#Heading7">Changing the DLL</A>
</UL>
<LI><A HREF="#Heading8">Creating and Using a Regular DLL</A>
<UL>
<LI><A HREF="#Heading9">Creating the Regular DLL</A>
<LI><A HREF="#Heading10">Adapting the Test Application</A>
</UL>
<LI><A HREF="#Heading11">Summary</A>
<LI><A HREF="#Heading12">Q&A</A>
<LI><A HREF="#Heading13">Workshop</A>
<UL>
<LI><A HREF="#Heading14">Quiz</A>
<LI><A HREF="#Heading15">Exercises</A>
</UL>
</UL>
<P>
<HR SIZE="4">
<BR>
Yesterday you learned how you could create a set of functionality that might be useful
for multiple applications and how you could package it in a library file that could
be linked into those applications. Today you will learn how to do this same thing,
only with a much more dynamic package.</P>
<P>Often, a family of applications will have some functionality in common. When you
place this shared functionality into DLLs instead of library modules, all the applications
can use the same functionality with only a single copy of the functionality distributed
in the form of DLLs, instead of duplicating the same functionality in each of the
applications. This method saves disk space on any systems where the applications
are installed.</P>
<P>Today, you will learn</P>
<P>
<UL>
<LI>About the different types of DLLs that you can create with Visual C++ and how
to determine which type best suits your needs.
<P>
<LI>How to build two of these types of DLLs and the different approaches for the
various DLL types.
<P>
<LI>How to use the functionality for both of these types of DLLs in a Visual C++
application.
<P>
<LI>How to determine when an application needs to be relinked when you make modifications
to a DLL that is used by the application.
</UL>
<H2><A NAME="Heading1"></A>Why Create DLLs?</H2>
<P>Dynamic link libraries (DLL) were introduced by Microsoft back in the early days
of Windows. DLLs are similar to library modules in that they both contain sets of
functionality that have been packaged for use by applications. The difference is
when the applications link to the library. With a library module (LIB), the application
is linked to the functionality in the library during the compile and build process.
The functionality contained in the library file becomes part of the application executable
file. With a DLL, the application links to the functionality in the library file
when the application is run. The library file remains a separate file that is referenced
and called by the application.</P>
<P>There are several reasons for creating DLLs instead of library module files. First,
you can reduce the size of the application executable files by placing functionality
that is used by multiple applications into DLLs that are shared by all of the applications.
You can update and modify functionality in the DLLs without having to update the
application executable (assuming that the exported interface for the DLL doesn't
change). Finally, you can use DLLs with just about any other Windows programming
language, which makes your functionality available to a wider number of programmers,
not just fellow Visual C++ programmers.</P>
<P>
<H3><A NAME="Heading2"></A>Creating and Using DLLs</H3>
<P>DLLs are library files with compiled code that can be used by other applications.
The DLLs expose certain functions and classes to these applications by exporting
the function. When a function is exported, it is added to a table that is included
in the DLL. This table lists the location of all exported functions contained in
the DLL, and it is used to locate and call each of these functions. Any functions
that are not exported are not added to this table, and they cannot be seen or called
by any outside application or DLL.</P>
<P>An application can call the functions in the DLL in two ways. The more involved
method of calling these functions is to look up the location of the desired function
in the DLL and get a pointer to this function. The pointer can then be used to call
the function.</P>
<P>The other, much easier way (and the only way that you'll use in any of the examples
in this book) is to link the application with the LIB file that is created with the
DLL. This LIB file is treated by the linker as a standard library file, just like
the one that you cre-ated yesterday. However, this LIB file contains stubs for each
of the exported functions in the DLL. A stub is a pseudo-function that has the same
name and argument list as the real function. In the interior of the function stub
is a small amount of code that calls the real function in the DLL, passing all of
the arguments that were passed to the stub. This allows you to treat the functions
in the DLL as if they were part of the application code and not as a separate file.</P>
<BLOCKQUOTE>
<P>
<HR>
<STRONG>NOTE:</STRONG> The LIB file for a DLL is automatically created for the DLL during
the compiling of the DLL. There is nothing extra that you need to do to create it.
<HR>
<P>
<HR>
<STRONG>TIP:</STRONG> Not only is it easier to create your applications using the LIB files
for any DLLs that you will be using, but also it can be safer when running the application.
When you use the LIB files, any DLLs that are used by your application are loaded
into memory the moment the application is started. If any of the DLLs are missing,
the user is automatically informed of the problem by Windows, and your application
does not run. If you don't use the LIB files, then you are responsible for loading
the DLL into memory and handling any errors that occur if the DLL cannot be found.
<HR>
</BLOCKQUOTE>
<P>There are two types of DLLs that you can easily create using Visual C++. These
two types are MFC extension DLLs and regular DLLs.</P>
<BLOCKQUOTE>
<P>
<HR>
<STRONG>NOTE:</STRONG> You can create other types of DLLs using Visual C++. All these other
types of DLLs involve a significant amount of ActiveX functionality, so they are
beyond the scope of this book. If you need to build ActiveX in-process server DLLs,
or other types of ActiveX DLLs, I recommend that you find an advanced book on Visual
C++ that provides significant coverage for these topics.
<HR>
</BLOCKQUOTE>
<H4>MFC Extension DLLs</H4>
<P>MFC DLLs are the easiest to code and create because you can treat them just like
any other collection of classes. For any classes that you want to export from the
DLL, the only thing that you need to add is the AFX_EXT_CLASS macro in the class
declaration, as follows:</P>
<P>
<PRE>class AFX_EXT_CLASS CMyClass
{
.
.
.
};
</PRE>
<P>This macro exports the class, making it accessible to Visual C++ applications.
You need to include this macro in the header file that is used by the applications
that will use the DLL, where it will import the class from the DLL so that it can
be used.</P>
<P>The one drawback to creating MFC extension DLLs is that they cannot be used by
any other programming languages. They can be used with other C++ compilers as long
as the compiler supports MFC (such as with Borland's and Symantec's C++ compilers).</P>
<P>
<H4>Regular DLLs</H4>
<P>The other type of DLL is a regular DLL. This type of DLL exports standard functions
from the DLL, not C++ classes. As a result, this type of DLL can require a little
more thought and planning than an MFC extension DLL. Once inside the DLL, you can
use classes all you want, but you must provide straight function calls to the external
applications.</P>
<P>To export a function, declare it as an export function by preceding the function
name with</P>
<P>
<PRE>extern "C" <function type> PASCAL EXPORT <function declaration>
</PRE>
<P>Include all this additional stuff in both the header file function prototype and
the actual source code. The extern "C" portion declares that this is a
standard C function call so that the C++ name mangler does not mangle the function
name. PASCAL tells the compiler that all function arguments are to be passed in PASCAL
order, which places the arguments on the stack in the reverse order from how they
are normally placed. Finally, EXPORT tells the compiler that this function is to
be exported from the DLL and can be called outside the DLL.</P>
<P>The other thing that you need to do to export the functions from your DLL is to
add all the exported function names to the DEF file for the DLL project. This file
is used to build the stub LIB file and the export table in the DLL. It contains the
name of the DLL, or library, a brief description of the DLL, and the names of all
functions that are to be exported. This file has to follow a specific format, so
you should not modify the default DEF file that is automatically created by the DLL
Wizard other than to add exported function names. A typical DEF file follows:</P>
<P>
<PRE>LIBRARY "mydll"
DESCRIPTION `mydll Windows Dynamic Link Library'
EXPORTS
; Explicit exports can go here
MyFunc1
MyFunc2
</PRE>
<P>If you are using MFC classes in your regular DLLs, you need to call the AFX_MANAGE_STATE
macro as the first line of code in all exported functions. This is necessary to make
the exported functions threadsafe, which allows your class functions to be called
simultaneously by two or more programs (or threads). The AFX_MANAGE_STATE macro takes
a single argument, a pointer to a AFX_MODULE_STATE structure, which can be retrieved
by calling the AfxGetStaticModuleState function. A typical exported function that
uses MFC looks like the following:</P>
<P>
<PRE>extern "C" void PASCAL EXPORT MyFunc(...)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
// normal function body here
.
.
.
}
</PRE>
<H3><A NAME="Heading3"></A>Designing DLLs</H3>
<P>When you are designing your DLLs, you should be aware that any of the functions
in your DLLs can be called simultaneously by multiple applications all running at
the same time. As a result, all the functionality in any DLLs that you create must
be threadsafe.</P>
<P>All variables that hold any values beyond each individual function call must be
held and maintained by the application and not the DLL. Any application variables
that must be manipulated by the DLL must be passed in to the DLL as one of the function
arguments. Any global variables that are manipulated within the DLL may be swapped
with variables from other application processes while the function is running, leading
to unpredictable results.</P>
<P>
<H2><A NAME="Heading4"></A>Creating and Using an MFC Extension DLL</H2>
<P>To see how easy it is to create and use an MFC extension DLL, you'll convert the
library module that you created yesterday into an MFC extension DLL today. After
you see how easy it is, and what types of changes you have to make to use the DLL,
you'll then reimplement the same functionality as a regular DLL so that you can get
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -