一、動態鏈接庫(DLL)介紹
1. Non-MFC DLL:
指的是不用MFC的類庫結構,直接用C語言寫的DLL,其輸出的函數一
般用的是標准C接口,並能被非MFC或MFC編寫的應用程序所調用。
2. Regular DLL:
和下述的Extension Dlls一樣,是用MFC類庫編寫的。明顯的特點是
在源文件里有一個繼承CWinApp的類。其又可細分成靜態連接到MFC和動態連接到MFC上
的。但靜態連接到MFC的動態連接庫只被VC的專業般和企業版所支持。
動態鏈接庫和MFC靜態鏈接:這種DLL在鏈接過程中會將使用到得MFC類庫復制一份到最終的DLL文件中
最終生成的DLL比較龐大且加載時不是很方便,但它可以在沒有MFC類庫DLL文件的機器上使用
動態鏈接庫使用共享MFC DLL:這種DLL不會將用到的MFC類庫復制到最終生成的DLL中,因此最終的DLL比較小,加載也很方便,但在沒有MFC類庫DLL文件的機器上無法使用,必須有MFC類庫的支持
3.Extension DLL:
MFC擴展DLL,可以實現從MFC所繼承下來的類的重新利用,可以導出C++類以及MFC派生類,使用這種DLL必須有MFC類庫的支持,也就是說它只被用MFC類庫所編寫的應用程序所調用。
二、編寫Non-MFC dll
1、打開visual studio 2008
2、file->new->Project…
3 、在彈出的“New project”窗口中,prject types子窗口中選擇 visual C++,Templates子窗口中選擇Win32 Project,然后在name處輸入 pow,location處輸入F:\vc2008dll,點擊“OK”
4、在彈出的“win32 application wizard - pow”窗口中,點擊“Next”;
5、在彈出的“win32 application wizard - pow”窗口中,Application type選項中選擇DLL,Additional options選項中選擇Export symbols,點擊“Finish”
工程會自動生成對應的文件和代碼,生成了pow.h和pow.cpp
6、在pow.h的文件末尾添加pow函數的聲明
POW_API int pow(const int& x,const int& y);
//POW_API是自動生成的一個宏,它的作用是表明該函數是導入還是導出的
7、在Pow.cpp中添加pow函數的實現
POW_API int pow(const int& x,const int& y)
{
int z=1;
for(int i=0;i<y;i++)
z*=x;
return z;
}
編譯后會在debug目錄里生成pow.dll和pow.lib兩個文件,其中pow.lib是動態鏈接庫進行靜態鏈接時使用
visual studio 2008默認的編譯dll的調用約定是cdecl,若用其它程序調用該dll請注意調用約定,否則某些dll中的函數會拋出異常。修改vs2008的調用約定-project-->properties-->configuration properties-->C/C++-->advanced-->calling convention-->選擇對應的方式!
三、靜態調用Non-MFCdll
方式一
1、創建一個Win32 Console Application工程,工程名為test1。
2、將pow.h和pow.dll和pow.lib拷貝到F:\c++\test1\test1目錄下,把Pow.dll拷貝一份放到F:\c++\test1\Debug目錄里防止直接運行exe時找不到dll。
3、將pow.h添加到test1工程中
4、修改test.Cpp文件如下:
#include "stdafx.h"
#include <iostream>
#include "pow.h"
#pragma comment(lib,"pow.h")
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
char a;
cout <<pow(3,3);
cin>>a;
return 0;
}
方式二
1、創建一個Win32 Console Application工程,工程名為test2。
2、將pow.dll和pow.lib拷貝到F:\c++\test2\test2目錄下,把Pow.dll拷貝一份放到F:\c++\test2\Debug目錄下防止直接運行exe時找不到dll。
3、新建一個頭文件命名為test2.h
其文件如下:
#pragma comment(lib,"pow.lib")
//不使用pragma comment,而直接在工程的Setting->Link頁的Object/Moduls欄填入notmfcdll.lib也可
__declspec(dllexport) int pow(const int& x,const int& y);
4、修改test.Cpp文件如下:
#include "stdafx.h"
#include "test2.h"
int _tmain(int argc, _TCHAR* argv[])
{
int a=0;
a=pow(3,6);
printf("%d",a);
char b;
b=getchar();
return 0;
}
三、動態調用Non-MFCdll
1、創建一個Win32 Console Application工程,工程名為test3。
2、將pow.dll拷貝到F:\c++\test3\test3目錄下,把Pow.dll拷貝一份放到F:\c++\test\Debug目錄下防止直接運行exe時找不到dll。
3、修改test3.Cpp文件如下:
#include <stdafx.h>
#include <stdio.h>
#include <windows.h>
typedef int (*MYPROC)( int, int);
int _tmain(int argc, _TCHAR* argv[])
{
int a=0;
char b;
HINSTANCE hInst;
MYPROC myproc;
//加載動態函數庫
hInst = LoadLibrary(L"pow.dll");
if( hInst != NULL)
{
myproc = (MYPROC)GetProcAddress( hInst,"pow" );//得到DLL中的函數的指針
a=myproc(2,3);
printf("%d",a);
FreeLibrary(hInst);//卸載DLL
}
else
{
a=1;
printf("%d",a);
}
b=getchar();
return 0;
}
按F5運行程序,拋出異常,調試發現GetProcAddress函數返回為空。
因為visual studio 2008編譯的dll導出函數是c++格式,而顯示調用GetProcAddress函數是按照C格式查找函數,所以需修改pow.h文件,將導出函數包含在extern "C"{}中,如下:
extern "C"
{
POW_API int pow(int x, int y);
}
重新編譯動態函數,將生成的pow.dll重新拷貝到調用dll的程序中就可以了!
導出函數包含在extern "C"{}中,使用靜態調用方式二的方法調用該dll時格式也許調整如下:
修改頭文件test2.h 即可,其文件如下:
#pragma comment(lib,"pow.lib")
__declspec(dllimport) int pow(const int& x,const int& y);