vc内幕4有。 步骤 1. 创建动态链接库 1) 选择N e w菜单命令打开Developer Studio 的N e w对话框。选择P r o j e c t标签和Wi n 3 2 Dynamic-Linked Library选项。给工程命名,单击O K按钮。S t u d i o将创建一个带有正确编译动 态链接库的设置的空工程。 一个动态链接库工程创建. l i b和. d l l文件的调试或发行版本。发行版本在性能上进行了优化, 而调试版本因调试符号而过于庞大。一个好的建议是改变. l i b和. d l l文件调试版本的名称,以使 得应用程序使用时不至于混淆。库的调试版本将不能正确地与应用程序的发行版本链接或执 行,反之亦然。 2) 为了重新命名库的调试版本,选择S t u d i o的P r o j e c t / S e t t i n g s菜单命令打开P r o j e c t S e t t i n g s对话框。找到S e t t i n g s组合框,选择Win32 Debug。然后,选择L i b r a r y标签,改变显示 在Output File Name编辑框中的名字。典型的做法是在所列的字符串后面加上一个字母“ d” 以标识调试版本。 S t d A f x . c p p和S t d A f x . h文件定义了应用程序可能需要的每一个运行库和M F C类。这些文件 被应用程序预编译过,以便只有原始代码被编译,而不是每次资源模块需编译时,再编译这 些大量的文件。对于C + +文件,自动假定为有这种特性。然而,本工程的C + +文件不使用 M F C类库,因此,必须使用如下方法关掉这个特性。 3) 对于C + +文件,必须改变工程中的设置,不使用预编译头。如前所示打开P r o j e c t S e t t i n g s对话框,改变所有配置的设置,在文件树中选取C + +文件,然后选择C / C + +标签。从 C a t e g o r y组合框中,选择Precompiled header ,对于每一个C + +文件,单击Not using precompiled headers。 2. 添加函数到动态链接库中 1) 引入或者创建. c或. c p p文件。 2) 若要允许库函数使用标准的C运行库,包含如下文件: # include <stdlib.h> 3) 若要允许库函数使用Windows API,包含如下文件: # include <windows.h> 动态链接库中有的函数可以被库外的其他函数所访问,而有的函数只能在内部被访问。 为了通知编译器和链接器,使函数可被外界所访问,需要用_declspec (dllexport)函数类型声 明该函数。然而,当要在应用程序中包含库的原型时,用户可能不想包含这个函数类型。为 了解决这个问题,我们创建了一个宏,当创建库时,有条件地表示d e c l s p e c ( d l l e x p o r t );而当 应用程序包含这些原型时,该宏无意义。 4) 添加下面的宏到定义库中函数原型的包含文件。 #ifdef WZDDLL_BLD #define DLL __declspec(dllexport) # e l s e #define DLL # e n d i f 5) 为了使D L L宏正常工作,需要在D L L工程设置中定义W Z D D L L _ B L D符号。选择 Developer Studio的P r o j e c t / S e t t i n g s菜单命令,打开Project Settings对话框。找到S e t t i n g s组合框, 选择All Configurations。然后选择C / C + +标签,添加W Z D D L L _ B L D到Preprocessor definitions 编辑框。 6) 使用D L L宏声明一个外部C函数,在函数的定义和实现处插入D L L宏。 void DLL WzdMessageBox(LPSTR pszString); void DLL WzdMessageBox(LPSTR pszString) { : : : } 7) 使用D L L宏声明一个外部C + +类,及声明它的所有函数为外部函数,只要在类的声明 处插入D L L宏。 class DLL CWzdDllCpp { } ; 8) 若想创建C库,必须在C包含文件的头和尾部加上如下代码,以便这个C包含文件可被 C或C + +文件使用。我们需要加入这个指令是因为C + +编译器给完全相同的函数名不同的内部 符号,而C却不是。符号名被链接器用来把应用程序对象链接在一起。为了强迫C + +编译器给 函数赋一个C符号名,需要使用e x t e r n " c "指令。然而,既然e x t e r n " c "指令将引发C编译器产生 一个语法错误,则在_ c p l u s p l u s被定义的情况下只能有条件地处理它。使用_ c p l u s p l u s指令是 因为当编译C + +文件时它为T R U E,而编译C文件时为FA L S E。最后的结果是,当这个文件包 含在C文件中,它正常处理。然而,在C + +文件中被编译时, C + +函数原型被强迫转换为C函 数原型。 /* at the start of your C .h file */ #ifdef __cplusplus extern "C" { # e l s e #endif /* __cplusplus */ : : : your C function prototypes : : : /* at the end of your C .h file */ #ifdef __cplusplus } # e n d i f 9) 关于C和C + +动态链接库函数,参见本节的“清单—动态链接C库实例”和“清单 —动态链接C + +库实例”。 3. 使用新动态链接库 通过打开目标工程的Project Settings对话框,选择L i n k标签,包含动态链接. l i b文件在其 他应用程序中,加入. l i b名称到Object/library modules编辑框中。并确认对于目标应用程序的 调试版本加入的是库的调试版本,对于目标应用程序的发行版本加入的是库的发行版本。否 则的话,目标应用程序不能被链接。为了运行应用程序,创建的. d l l文件必须放到系统执行 路径下,或者是由系统的PAT H环境参数指定的一个路径之下。
动态链接C库实例 /* WzdDll.h : NonMFC Dll * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * / #if !defined WZDDLL_H #define WZDDLL_H #ifdef __cplusplus extern "C” { # e l s e #endif /* __cplusplus */ #ifdef WZDDLL_BLD #define DLL __declspec(dllexport) # e l s e #define DLL # e n d i f void DLL WzdMessageBox(LPSTR pszString); void DLL DestroyWzdWindow(HWND hWnd); void DLL WzdFunc3(BOOL b); #ifdef __cplusplus } # e n d i f # e n d i f / * * WzdDll.c : NonMFC "C" Dll Using the Win32 API directly * / #include <windows.h> #include <stdlib.h> #include "WzdDll.h" BOOL flag=FA L S E ; // must call Win32 API directly void DLL WzdMessageBox(LPSTR pszString) { MessageBox(NULL,pszString,"Wzd DLL",MB_OK); } void DLL DestroyWzdWindow(HWND hWnd) { D e s t r o y Wi n d o w ( h W n d ) ; } void DLL WzdFunc3(BOOL b) { f l a g = b ; } 清单—动态链接C++库实例 // WzdDllCpp.h : C++ NonMFC Dll / / #if !defined WZDDLLCPP_H #define WZDDLLCPP_H #ifdef WZDDLL_BLD #define DLL __declspec(dllexport) # e l s e #define DLL # e n d i f class DLL CWzdDllCpp { BOOL m_bFlag; p u b l i c : C W z d D l l C p p ( ) ; ~ C W z d D l l C p p ( ) ; void WzdMessageBox(LPSTR pszString); void DestroyWzdWindow(HWND hWnd); void WzdFunc3(BOOL b); } ; # e n d i f // WzdDllCpp.cpp : NonMFC "C++" Dll Using the Win32 API directly / / #include <windows.h> #include <stdlib.h> #include "WzdDllCpp.h" C W z d D l l C p p : : C W z d D l l C p p ( ) { m _ b F l a g = FA L S E ; } C W z d D l l C p p : : ~ C W z d D l l C p p ( ) { } // must call the Win32 API directly void CWzdDllCpp::WzdMessageBox(LPSTR pszString) { MessageBox(NULL,pszString,"Wzd DLL Cpp",MB_OK); } void CWzdDllCpp::DestroyWzdWindow(HWND hWnd) { D e s t r o y Wi n d o w ( h W n d ) ; } void CWzdDllCpp::WzdFunc3(BOOL b) { m _ b F l a g = b ; }
步骤
1. 创建动态链接库
1) 选择N e w菜单命令打开Developer Studio 的N e w对话框。选择P r o j e c t标签和Wi n 3 2
Dynamic-Linked Library选项。给工程命名,单击O K按钮。S t u d i o将创建一个带有正确编译动
态链接库的设置的空工程。
一个动态链接库工程创建. l i b和. d l l文件的调试或发行版本。发行版本在性能上进行了优化,
而调试版本因调试符号而过于庞大。一个好的建议是改变. l i b和. d l l文件调试版本的名称,以使
得应用程序使用时不至于混淆。库的调试版本将不能正确地与应用程序的发行版本链接或执
行,反之亦然。
2) 为了重新命名库的调试版本,选择S t u d i o的P r o j e c t / S e t t i n g s菜单命令打开P r o j e c t
S e t t i n g s对话框。找到S e t t i n g s组合框,选择Win32 Debug。然后,选择L i b r a r y标签,改变显示
在Output File Name编辑框中的名字。典型的做法是在所列的字符串后面加上一个字母“ d”
以标识调试版本。
S t d A f x . c p p和S t d A f x . h文件定义了应用程序可能需要的每一个运行库和M F C类。这些文件
被应用程序预编译过,以便只有原始代码被编译,而不是每次资源模块需编译时,再编译这
些大量的文件。对于C + +文件,自动假定为有这种特性。然而,本工程的C + +文件不使用
M F C类库,因此,必须使用如下方法关掉这个特性。
3) 对于C + +文件,必须改变工程中的设置,不使用预编译头。如前所示打开P r o j e c t
S e t t i n g s对话框,改变所有配置的设置,在文件树中选取C + +文件,然后选择C / C + +标签。从
C a t e g o r y组合框中,选择Precompiled header ,对于每一个C + +文件,单击Not using
precompiled headers。
2. 添加函数到动态链接库中
1) 引入或者创建. c或. c p p文件。
2) 若要允许库函数使用标准的C运行库,包含如下文件:
# include <stdlib.h>
3) 若要允许库函数使用Windows API,包含如下文件:
# include <windows.h>
动态链接库中有的函数可以被库外的其他函数所访问,而有的函数只能在内部被访问。
为了通知编译器和链接器,使函数可被外界所访问,需要用_declspec (dllexport)函数类型声
明该函数。然而,当要在应用程序中包含库的原型时,用户可能不想包含这个函数类型。为
了解决这个问题,我们创建了一个宏,当创建库时,有条件地表示d e c l s p e c ( d l l e x p o r t );而当
应用程序包含这些原型时,该宏无意义。
4) 添加下面的宏到定义库中函数原型的包含文件。
#ifdef WZDDLL_BLD
#define DLL __declspec(dllexport)
# e l s e
#define DLL
# e n d i f
5) 为了使D L L宏正常工作,需要在D L L工程设置中定义W Z D D L L _ B L D符号。选择
Developer Studio的P r o j e c t / S e t t i n g s菜单命令,打开Project Settings对话框。找到S e t t i n g s组合框,
选择All Configurations。然后选择C / C + +标签,添加W Z D D L L _ B L D到Preprocessor definitions
编辑框。
6) 使用D L L宏声明一个外部C函数,在函数的定义和实现处插入D L L宏。
void DLL WzdMessageBox(LPSTR pszString);
void DLL WzdMessageBox(LPSTR pszString)
{
: : :
}
7) 使用D L L宏声明一个外部C + +类,及声明它的所有函数为外部函数,只要在类的声明
处插入D L L宏。
class DLL CWzdDllCpp
{
} ;
8) 若想创建C库,必须在C包含文件的头和尾部加上如下代码,以便这个C包含文件可被
C或C + +文件使用。我们需要加入这个指令是因为C + +编译器给完全相同的函数名不同的内部
符号,而C却不是。符号名被链接器用来把应用程序对象链接在一起。为了强迫C + +编译器给
函数赋一个C符号名,需要使用e x t e r n " c "指令。然而,既然e x t e r n " c "指令将引发C编译器产生
一个语法错误,则在_ c p l u s p l u s被定义的情况下只能有条件地处理它。使用_ c p l u s p l u s指令是
因为当编译C + +文件时它为T R U E,而编译C文件时为FA L S E。最后的结果是,当这个文件包
含在C文件中,它正常处理。然而,在C + +文件中被编译时, C + +函数原型被强迫转换为C函
数原型。
/* at the start of your C .h file */
#ifdef __cplusplus
extern "C" {
# e l s e
#endif /* __cplusplus */
: : :
your C function prototypes
: : :
/* at the end of your C .h file */
#ifdef __cplusplus
}
# e n d i f
9) 关于C和C + +动态链接库函数,参见本节的“清单—动态链接C库实例”和“清单
—动态链接C + +库实例”。
3. 使用新动态链接库
通过打开目标工程的Project Settings对话框,选择L i n k标签,包含动态链接. l i b文件在其
他应用程序中,加入. l i b名称到Object/library modules编辑框中。并确认对于目标应用程序的
调试版本加入的是库的调试版本,对于目标应用程序的发行版本加入的是库的发行版本。否
则的话,目标应用程序不能被链接。为了运行应用程序,创建的. d l l文件必须放到系统执行
路径下,或者是由系统的PAT H环境参数指定的一个路径之下。
/* WzdDll.h : NonMFC Dll
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
#if !defined WZDDLL_H
#define WZDDLL_H
#ifdef __cplusplus
extern "C” {
# e l s e
#endif /* __cplusplus */
#ifdef WZDDLL_BLD
#define DLL __declspec(dllexport)
# e l s e
#define DLL
# e n d i f
void DLL WzdMessageBox(LPSTR pszString);
void DLL DestroyWzdWindow(HWND hWnd);
void DLL WzdFunc3(BOOL b);
#ifdef __cplusplus
}
# e n d i f
# e n d i f
/ *
* WzdDll.c : NonMFC "C" Dll Using the Win32 API directly
* /
#include <windows.h>
#include <stdlib.h>
#include "WzdDll.h"
BOOL flag=FA L S E ;
// must call Win32 API directly
void DLL WzdMessageBox(LPSTR pszString)
{
MessageBox(NULL,pszString,"Wzd DLL",MB_OK);
}
void DLL DestroyWzdWindow(HWND hWnd)
{
D e s t r o y Wi n d o w ( h W n d ) ;
}
void DLL WzdFunc3(BOOL b)
{
f l a g = b ;
}
清单—动态链接C++库实例
// WzdDllCpp.h : C++ NonMFC Dll
/ /
#if !defined WZDDLLCPP_H
#define WZDDLLCPP_H
#ifdef WZDDLL_BLD
#define DLL __declspec(dllexport)
# e l s e
#define DLL
# e n d i f
class DLL CWzdDllCpp
{
BOOL m_bFlag;
p u b l i c :
C W z d D l l C p p ( ) ;
~ C W z d D l l C p p ( ) ;
void WzdMessageBox(LPSTR pszString);
void DestroyWzdWindow(HWND hWnd);
void WzdFunc3(BOOL b);
} ;
# e n d i f
// WzdDllCpp.cpp : NonMFC "C++" Dll Using the Win32 API directly
/ /
#include <windows.h>
#include <stdlib.h>
#include "WzdDllCpp.h"
C W z d D l l C p p : : C W z d D l l C p p ( )
{
m _ b F l a g = FA L S E ;
}
C W z d D l l C p p : : ~ C W z d D l l C p p ( )
{ }
// must call the Win32 API directly
void CWzdDllCpp::WzdMessageBox(LPSTR pszString)
{
MessageBox(NULL,pszString,"Wzd DLL Cpp",MB_OK);
}
void CWzdDllCpp::DestroyWzdWindow(HWND hWnd)
{
D e s t r o y Wi n d o w ( h W n d ) ;
}
void CWzdDllCpp::WzdFunc3(BOOL b)
{
m _ b F l a g = b ;
}