`
Gene
  • 浏览: 51254 次
社区版块
存档分类
最新评论

Creating a DLL in Visual Studio Dot Net

阅读更多
<!---->
<!---->
   Creating a DLL in Visual Studio Dot Net  
Stats
  Rating: 3.54 out of 5 by 13 users
  Submitted: 01/08/03
[[ Havyck ]] (adonisv@oblyvion.com)
<!---->

 
Creating a DLL in Visual Studio Dot Net

Creating a DLL in Visual Studio Dot Net is similar to creating one in Visual Studio. This tutorial will focus on 1) how to build the DLL and link it with your client application, and 2) the procedural steps needed to complete this task in Visual Studio Dot Net.

What is a DLL?

“DLL” stands for dynamic-link library. A dynamic-link library is an executable file that acts as a shared library of functions. Dynamic linking provides a way for a process to call a function that is not part of its executable code. The executable code for the function is located in a DLL, which contains one or more functions that are compiled, linked, and stored separately from the processes that use them. DLLs also facilitate the sharing of data and resources. Multiple applications can simultaneously access the contents of a single copy of a DLL in memory.

Dynamic linking differs from static linking in that it allows an executable module (either a DLL or .EXE file) to include only the information needed at run time to locate the executable code for a DLL function. In static linking, the linker gets all of the referenced functions from the static link library and places it with your code into your executable.

Using dynamic linking instead of static linking offers several advantages. DLLs save memory, reduce swapping, save disk space, upgrade easier, provide after-market support, provide a mechanism to extend the MFC library classes, support Multilanguage programs, and ease the creation of international versions.
The different kind of DLL’s available in Dot Net.

Using Visual C++, you can build Win32 DLLs in C or C++ that do not use the Microsoft Foundation Class Library (MFC). You can create a non-MFC DLL project with the Win32 Application Wizard.
The MFC library itself is available, in either static link libraries or in a number of DLLs, with the MFC DLL Wizard. If your DLL is using MFC, Visual C++ supports three different DLL development scenarios:

· Building a regular DLL that statically links MFC.
· Building a regular DLL that dynamically links MFC.
· Building an MFC extension DLL. These always dynamically link MFC.

This tutorial will focus only on the regular and MFC extension DLL.

Each DLL has some kind of interface. The interface is the set of the variables, pointers, functions or classes provided by the DLL that you can access from the client program. It is this interface that allows the client program to utilize the DLL. An MFC extension DLL can have a C++ style interface. That is, it can provide, or export, C++ functions and entire C++ classes to be used by the client application. The functions it exports can use C++ or MFC data types as parameters or as return values. When the DLL exports a class, the client will be able to create instances of that class or derive new classes from it. Inside the DLL, you can also use MFC and C++.
The MFC code library used by Visual C++ is stored in a DLL. An MFC extension DLL dynamically links to the MFC code library DLL. The client application must also dynamically link to the MFC code library DLL. As the years have gone by the MFC library has grown. As a result, Microsoft created several versions of the MFC code library DLL. Both the client program and the extension DLL must be built using the same version of MFC. Therefore, for an MFC extension DLL to work, both the extension DLL and the client program must dynamically link to the same MFC code library DLL, and this must be available on the computer where the application is running.

MFC extension. DLLs are very small. You can build an extension DLL that exports a few functions or small classes and has a size of 10-15 KB. Obviously, the size of your DLL depends on how much code you store in it, but in general an MFC extension DLL is relatively small.

Regular DLLs

The MFC extension DLL only works with MFC client applications. If you need a DLL that can be loaded and run by a wider range of Win32 programs, you should use a regular DLL. The downside is that your DLL and your client application will not be able to send each other pointers or references to MFC-derived classes and objects. If you export a function from your DLL, that function cannot use MFC data types in any of its parameters or return values. If you export a C++ class from your DLL, it cannot be derived from MFC. You can still use MFC inside your DLL, but not in your interface.

Your regular DLL still needs to have access to the code in the MFC code library DLL. You can dynamically or statically link to this code. If you dynamically link, that means the MFC code your DLL needs in order to function is not built into your DLL. Your DLL will get the code it needs from the MFC code library DLL found on the client application's computer. If the right version of the MFC code library DLL is not there, your DLL won't run. Like the MFC extension DLL, you get a small DLL (because the DLL doesn't include the MFC code), but you can only run if the client computer has the MFC code library DLL.


If you statically link to the MFC code library, your DLL will incorporate within itself all the MFC code it needs. Thus, it will be larger, but it won't be dependent on the client computer having the proper code library. If you can't rely on the host computer having the right version of MFC available, you should use static linking. If you have control over which versions of the MFC DLLs are installed on the client computers, or if your installation program also loads the right MFC DLL, dynamic linking would be appropriate.

Creating a DLL

You can make an MFC-based DLL with the MFC DLL Wizard. Select "File | New | Project" from the menu.

On the "Project" tab, select "MFC DLL." Pick a name for your new project.

Also pick a location for your new project or accept the default setting and click "OK." The MFC DLL Wizard opens a dialog window and you will see two links. One entitled “Overview,” and the other “Application Settings.”

In the Overview section, you will see the following information:
These are the current project settings:
Create a regular DLL (MFC shared)
Click Finish from any window to accept the current settings.
After you create the project, see the project's readme.txt file for information about the project features and files that are generated.

Under the Application Settings link you will see the following information

DLL type:
Regular DLL using shared MFC
Regular DLL with MFC statically linked
MFC extension DLL

Additional features:
Automation
Windows sockets

Under Application Settings, you have the choice of creating an MFC extension DLL, a regular DLL "using shared MFC DLL" (i.e., a regular DLL dynamically linked to MFC), or a regular DLL statically linked to MFC. Pick the one you want and click "Finish." Ignore the additional features for this tutorial.

The MFC DLL Wizard builds a DLL, which doesn't do anything. The new DLL will compile, but since it doesn't export any classes or functions yet, it is still essentially useless. You now have two jobs: (1) add functionality to make your DLL useful; and (2) modify your client application to use your DLL.

Exporting a class

Once you're done with the MFC DLL Wizard, you can add classes to your DLL by adding the .CPP and .H files from another project, or you can create your own within the current project. To export a class, you add "__declspec(dllexport)" macro to the class declaration so it looks like this:

class __declspec(dllexport) CNewClass
{
//Your class declaration will go here.
};

If you are making an MFC extension DLL, you can use the AFX_EXT_CLASS macro:

class AFX_EXT_CLASS CNewClass
{
//Your class declaration will go here.
};

There are other ways to export a class, but this one is the easiest.
Exporting variables, constants and objects
Instead of exporting a whole class, you can have your DLL export a variable, constant or object. To export a variable or constant, you simply add the “__declspec(dllexport)” marco to its declaration.
__declspec(dllexport) double m_dYourDouble;
__declspec(dllexport) extern const COLORREF m_clrYourColor =
RGB(44,11,77);
If you want to export a constant, you must use the "extern" specifier. Otherwise you will get a link error.
You can declare and export a class object in the same manner:
__declspec(dllexport) CMatrix m_cmColumnMatrix(1,4);

Note that you can only export a class object if the client application recognizes the class and has its header file. If you make a new class inside your DLL, the client application won't recognize it without the header file.
For example, in a project called Utilize Dynamic Link Library, the header file for that project (UtilizeDynamicLinkLibrary.h) will contain the include files for all exported classes that the project wishes to use.


// UtilizeDynamicLinkLibrary.h : main header file for the PROJECT_NAME application
//

#pragma once

#ifndef __AFXWIN_H__
#error include 'stdafx.h' before including this file for PCH
#endif

#include "resource.h" // main symbols
#include "../Experimental/Node.h" // imported class
#include "../Experimental/List.h" // imported class
#include "../Experimental/CommunalIncludes.h" //imported class

When you export a variable or object, each client application that loads the DLL will get its own copy. Thus, if two different applications are using the same DLL, changes made by one application will not affect the other application.
It's important to remember that you can only export objects and variables that are of global scope within your DLL. Local objects and variables cease to exist when they go out of scope. Thus, if your DLL included the following, it wouldn't work.
YourFunction( )
{
__declspec(dllexport) CInterestingClass FascinatingObject;
__declspec(dllexport) int CuriousInt;
}

As soon as the object and variable go out of scope, they will cease to exist.
Exporting a function
Exporting functions is similar to exporting objects or variables. You simply add the “_declspec(dllexport)” macro to the beginning of your function prototype:

__declspec(dllexport) int RadicalFunction(int);
If you are making an MFC regular DLL that will be used by a client application written in C, your function declaration should look like this:

extern "C" __declspec(dllexport) int IntricateFunction(int);


Your function definition should look like this:
extern "C" __declspec(dllexport) int IntricateFunction(int x)
{
//Perform an operation that will dazzle your professors.
}

If you are building a regular DLL that is dynamically linked to the MFC code library DLL, you must insert the AFX_MANAGE_STATE macro as the first line of any exported function. Thus, your function definition would look like this:

extern "C" __declspec(dllexport) int AddFive(int x)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
return x + 5;
}

It’s acceptable to do this in every regular DLL. If you switch your DLL to static linking, the macro will simply have no effect.
Remember, only an MFC extension DLL can export functions with MFC data types in the parameters or return value.
Exporting a pointer
Exporting a pointer that has not been initialized is simple. Again you place the “__declspec(dllexport)” macro in front of the declaration.

__declspec(dllexport) int* LargeInt;

You can also export an initialized object this way:
__declspec(dllexport) CSomeClass* NeutralPointer =
new CInterestingClass;
Of course, if you declare and initialize your pointer you need to find a place to delete it.


In an extension DLL, you will find a function called DllMain( ). This function is called when the client program attaches your DLL and again when it detaches. So here's one possible way to handle your pointers in an extension DLL:
#include "BaseClass.h"

_declspec(dllexport) CBaseClass* SharpPointer = new CBaseClass;

DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpReserved)
{
if (dwReason == DLL_PROCESS_ATTACH)
{

}
else if (dwReason == DLL_PROCESS_DETACH)
{
delete SharpPointer;
}
}

A regular DLL looks more like an ordinary MFC executable. It has an object derived from CWinApp to handle opening and closing your DLL. You can use the class wizard to add an InitInstance( ) function and an ExitInstance( ) function.

int CMyDllApp::ExitInstance()
{
delete DullPointer;
return CWinApp::ExitInstance();
}

Using the DLL in a client application
A DLL can't run without a client application. The client application must load it and use its interface.

When you compile your DLL, the compiler creates two important files, the .DLL file and the .LIB file. Your client application needs both of these. You must copy them into the project folder of your client application. If you link the .LIB file to your client application, by adding it to your project, you won’t need to update the .LIB file every time you change and recompile your DLL. (Click the name of your project in the solution explorer, then right click and choose “Add,” then “Add Existing Item.” Navigate to the directory where the .LIB file is located. Click on the .LIB file and click “Open.”) The DLL and .LIB files that are created when you build in Debug are different than those built when you build in Release. When you are building your client application in Debug, you need the Debug versions of the DLL and .LIB files, and when you are building in Release you need the Release DLL and .LIB.

The easiest way to handle this is to put the Debug DLL and .LIB files in your client application's Debug folder and the Release DLL and .LIB in the Release folder.

The next step is to go into your client project settings and tell the linker to look for your .LIB file. You must tell the linker the name of your .LIB file and where it can be found. To do this, in the Solution explorer, click on the name of your client application then click the “Property (Pages)” icon. When the Property dialog opens up, click the folder on the left marked “Linker,” and then click “General.” Locate the text entry box marked “Additional Libraries and Directories.” This attribute setting is used to specify one or more additional paths to search for libraries. You may either type in the directory where the .LIB file can be found or use the browse button to locate it. After you have located the directory where the file can be found, click OK.

In addition to the DLL and .LIB files, your client application needs a header file for the imported classes, functions, objects and variables. When we were exporting, we added "__declspec(dllexport)" to our declarations. Now that we are importing, we will add "__declspec(dllimport)." So if you want to import the variable, object and function used in our previous examples, your header file will contain the following:

__declspec(dllimport) int IntricateFunction(int);
__declspec(dllexport) CBaseClass InstanceObject;
__declspec(dllexport) int LargeInt;

Remember, if you used the extern "C" specifier in the DLL, you must also use it in the client application:

extern "C" __declspec(dllimport) int SomeFunction(int);
To make things more readable, we might write it like this instead:
#define DLLIMPORT __declspec(dllimport)

DLLIMPORT int SomeFunction(int);
DLLIMPORT CSomeClass SomeObject;
DLLIMPORT int SomeInt;

Now that you have declared your object, variable and function in a header file inside your client application, they are available for use.
To import an entire class, you can simply include the header file for that class as shown above.


Once you are done building your client application and you're ready to turn it over to the actual users, you should give them your Release executable and the Release DLL. You do not need to give the users the .LIB file. The DLL can go in the same directory as the executable, or it can go in the Windows System directory. As discussed above, you may also have to provide your users with the correct MFC code library DLL. This DLL was loaded onto your computer when you installed Visual C++. Your users, however, may not have it. It does not come standard with Windows.

This tutorial is based on two references. MFC Tutorial , Part 1 by Andrew Fenster and the Online Help in Visual Studio Dot Net. The purpose of this tutorial is to illustrate the process for building a DLL and linking it with a client application using Visual Studio Dot Net. It also simplifies the process of the previous example provided by Andrew Fenster.

<script language="JavaScript" type="text/javascript"> <!----> </script> <script src="http://www.kenlet.com/javascripts/gizmo.js" language="JavaScript" type="text/javascript"> </script>
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics