Visual C++6.0 中可实现的DLL
Visual C++6.0 支持自动生成Win32 DLL和MFC AppWizard DLL两种,其中Win32 DLL不使用MFC类库,其导出的函数是标准的C接口,能够被非MFC和MFC的应用程序调用,应用范围更广泛。所以下面就介绍Win32 DLL的开发。
创建导出函数的Win32 DLL
1、启动Visual C++6.0,利用AppWizard创建一个“Win32 Dynamic-Link Library”类型的工程,工程名为SayHello。采用默认设置,即创建一个Win32 DLL的空项目。
2、为DLL工程添加头文件SayHello.h和源文件SayHello.cpp。在头文件SayHello.h中,声明DLL的导出函数Say和Sum,分别用来显示"Hello,World!"和求和。声明代码如下:
//
SayHello.h
//
/*
extern "C"修饰词的作用是使C++编译器以C语言的方式对这个函数进行处理,以便供其他语言所用。
*/
extern " C " void _declspec(dllexport)Say( char * szWords, int nLen); // 声明Say导出函数
extern " C " float _declspec(dllexport)Sum( float fNum1, float fNum2); // 声明Sum导出函数
//
/*
extern "C"修饰词的作用是使C++编译器以C语言的方式对这个函数进行处理,以便供其他语言所用。
*/
extern " C " void _declspec(dllexport)Say( char * szWords, int nLen); // 声明Say导出函数
extern " C " float _declspec(dllexport)Sum( float fNum1, float fNum2); // 声明Sum导出函数
在源文件SayHello.cpp中添加函数Say和Sum的实现代码,代码如下:
//
SayHello.cpp
//
#include < string .h >
#include " SayHello.h "
void Say( char * szWords, int nLen)
{
strcpy(szWords, " Hello,World! " );
strcat(szWords, " \0 " );
}
float Sum( float fNum1, float fNum2)
{
return fNum1 + fNum2;
}
//
#include < string .h >
#include " SayHello.h "
void Say( char * szWords, int nLen)
{
strcpy(szWords, " Hello,World! " );
strcat(szWords, " \0 " );
}
float Sum( float fNum1, float fNum2)
{
return fNum1 + fNum2;
}
3、【F7】键编译生成DLL。此时在工程的Debug文件夹下生成实际代码文件SayHello.dll和导入库文件SayHello.lib。
4、从DLL中导出函数有两种方法,一种是使用_declspec(dllexport)关键字,如SayHello.h中所示;一种是添加.def文件(值得注意的是,添加的文件类型是文本文件,且名称应输入SayHello.def),代码如下:
;SayHello.def
;
LIBRARY " SayHello "
DESCRIPTION " 导出DLL中的函数 "
EXPORTS
Say @ 1
Sum @ 2
;
LIBRARY " SayHello "
DESCRIPTION " 导出DLL中的函数 "
EXPORTS
Say @ 1
Sum @ 2
5、加载DLL分为静态加载和动态加载。动态加载(运行时动态链接,也叫显示链接)DLL是通过LoadLibrary、GetProcAddress和FreeLibrary这3个API函数进行的。调用如下:
typedef
void
(
*
SAY)(
char
*
,
int
);
SAY Say;
typedef float ( * SUM)( float , float );
SUM Sum;
HINSTANCE hdll;
hdll = LoadLibrary( " ..\\..\\SayHello\\Debug\\SayHello.dll " );
if (hdll != NULL)
{
// GetProcAddress函数获得获得获得DLL导出函数地址
Say = (SAY)GetProcAddress(hdll, " Say " );
Sum = (SUM)GetProcAddress(hdll, " Sum " );
}
else
{
AfxMessageBox( " 无法加载DLL! " );
return ;
}
UpdateData(TRUE);
const int Len = 20 ;
char p[Len];
Say(p,Len);
m_strDispHello.Format( " %s " ,p);
SAY Say;
typedef float ( * SUM)( float , float );
SUM Sum;
HINSTANCE hdll;
hdll = LoadLibrary( " ..\\..\\SayHello\\Debug\\SayHello.dll " );
if (hdll != NULL)
{
// GetProcAddress函数获得获得获得DLL导出函数地址
Say = (SAY)GetProcAddress(hdll, " Say " );
Sum = (SUM)GetProcAddress(hdll, " Sum " );
}
else
{
AfxMessageBox( " 无法加载DLL! " );
return ;
}
UpdateData(TRUE);
const int Len = 20 ;
char p[Len];
Say(p,Len);
m_strDispHello.Format( " %s " ,p);
GetDlgItem(IDC_EDIT1)->SetWindowText(m_strDispHello);
//m_cedit1.SetWindowTextA(m_strDispHello);
//m_cedit1.SetWindowTextA(m_strDispHello);
m_fResult=Sum(3.0f,4.0f);
m_strDispHello.Format("%f",m_fResult);
m_cedit2.SetWindowTextA(m_strDispHello);*/
//GetDlgItem(IDC_EDIT2)->SetWindowText(m_strDispHello);
//UpdateData(FALSE);
FreeLibrary(hdll);
UpdateData(FALSE);
FreeLibrary(hdll);
静态加载(加载时动态链接,也叫隐式链接)DLL是由编译系统完成对DLL的加载和应用程序结束时对DLL的卸载,需要将DLL的引用库文件(.lib)与应用程序进行静态链接。调用如下:
m_strDispHello.Format("%f",m_fResult);
m_cedit2.SetWindowTextA(m_strDispHello);*/
//GetDlgItem(IDC_EDIT2)->SetWindowText(m_strDispHello);
//UpdateData(FALSE);
FreeLibrary(hdll);
UpdateData(FALSE);
FreeLibrary(hdll);
#pragma comment(lib,
"
SayHello.lib
"
)
extern " C " _declspec(dllimport) void Say( char * szWords, int nLen); //编译生成更高效的代码
extern " C " _declspec(dllimport) float Sum( float fNum1, float fNum2);
此时就使用Say和Sum函数了。
extern " C " _declspec(dllimport) void Say( char * szWords, int nLen); //编译生成更高效的代码
extern " C " _declspec(dllimport) float Sum( float fNum1, float fNum2);