一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

C 下的DLL編程入門

 星光閃亮圖書館 2021-06-25

一、   編寫第一個(gè)入門級dll文件

1. 新建一個(gè)dlltest的dll工程,加入一源文件dlltest.cpp,包含add和subtract兩個(gè)函數(shù)如下:

_declspec(dllexport) int add(int a,int b) { return a+b; } _declspec(dllexport) int subtract(int a,int b) { return a-b; }

注意:

在函數(shù)名前加上_declspec(dllexport),這樣編譯后在連接的時(shí)候才會(huì)生成dlltest.lib(引入庫文件)和dlltest.exp(輸出庫文件),并且在命令提示符下用dumpbin命令可以看到導(dǎo)出了哪些函數(shù)。

方法:在命令提示符下,轉(zhuǎn)到dll文件所在目錄下,輸入dumpbin –exports dlltest.dll,列出導(dǎo)出函數(shù)如下:

這里注意到函數(shù)名字已經(jīng)被改成了?add@@YAHHH@Z,這種現(xiàn)象叫做名字粉碎,是為了支持函數(shù)重載而做的。

2.編寫一個(gè)基于對話框的MFC程序測試DLL,工程名為calldll,放置兩個(gè)按紐add和subtract,響應(yīng)按紐消息,調(diào)用這個(gè)DLL的add和subtract函數(shù)。

先添加響應(yīng)按鈕消息的函數(shù)OnAdd和OnSubtract,然后在函數(shù)所在源文件中寫完整函數(shù)體如下:

//extern int add(int,int);
//extern int subtract(int,int);
_declspec(dllimport) int add(int,int);
_declspec(dllimport) int subtract(int,int);

void CCalldllDlg::OnAdd() 
{
    // TODO: Add your control notification handler code here
    CString str;
    str.Format('2+3=%d',add(2,3));
    MessageBox(str);
}

void CCalldllDlg::OnSubtract() 
{
    // TODO: Add your control notification handler code here
    CString str;
    str.Format('3-2=%d',subtract(3,2));
    MessageBox(str);
}


這里采用隱式鏈接的方式加載動(dòng)態(tài)鏈接庫:

注意:要用關(guān)鍵字extern先聲明這兩個(gè)函數(shù),表明這兩個(gè)函數(shù)是在外部定義的(不過程序中將它注釋掉了)。最好是用_declspec(dllimport)表明函數(shù)是從動(dòng)態(tài)鏈接庫的lib文件中引入的,這樣效率更高。

將文件dlltest.lib拷貝到此工程目錄下,并在Project Settings的Link標(biāo)簽下添加此文件:(否則編譯會(huì)成功,但連接時(shí)會(huì)出錯(cuò)提示找不到函數(shù)的定義)

 

編譯連接生成calldll.exe,這時(shí)用Dumpbin -importscalldll.exe查看它的輸入信息,可以看到它加載了dlltest.dll。

運(yùn)行calldll.exe(要成功運(yùn)行還需將dlltest.dll拷貝到工程目錄或此exe所在目錄下)

 

這樣,最簡單的第一個(gè)dll就完成了。

二、   編寫涉及到類和頭文件的dll文件

1.  新建一個(gè)dlltest的dll工程,加入一頭文件dlltest.h和一源文件dlltest.cpp。

dlltest.h:

#ifdef DLL_API #else #define DLL_API _declspec(dllimport) #endif DLL_API int add(int,int); DLL_API int subtract(int,int); class DLL_API Point1 //將整個(gè)類導(dǎo)出 { public: void output(int x,int y); void output1(int x,int y); }; class Point2 { public: DLL_API void output(int x,int y); //僅導(dǎo)出類中的一個(gè)函數(shù) void output1(int x,int y); };


dlltest.cpp

#define DLL_API _declspec(dllexport)
#include 'dlltest.h'
#include <windows.h>
#include <stdio.h>

int add(int a,int b)
{
    return a+b;
}

int subtract(int a,int b)
{
    return a-b;
}

void Point1::output(int x,int y)
{
    HWND hwnd=GetForegroundWindow();
    HDC hdc=GetDC(hwnd);
    char buf[50];
    memset(buf,0,50);
    sprintf(buf,'x=%d,y=%d',x,y);
    TextOut(hdc,0,0,buf,strlen(buf));
}

void Point1::output1(int x,int y)
{
    HWND hwnd=GetForegroundWindow();
    HDC hdc=GetDC(hwnd);
    char buf[50];
    memset(buf,0,50);
    sprintf(buf,'x=%d,y=%d',x,y);
    TextOut(hdc,0,0,buf,strlen(buf));
}

void Point2::output(int x,int y)
{
    HWND hwnd=GetForegroundWindow();
    HDC hdc=GetDC(hwnd);
    char buf[50];
    memset(buf,0,50);
    sprintf(buf,'x=%d,y=%d',x,y);
    TextOut(hdc,0,20,buf,strlen(buf));
}

void Point2::output1(int x,int y)
{
    HWND hwnd=GetForegroundWindow();
    HDC hdc=GetDC(hwnd);
    char buf[50];
    memset(buf,0,50);
    sprintf(buf,'x=%d,y=%d',x,y);
    TextOut(hdc,0,20,buf,strlen(buf));
}


2.  編寫一個(gè)基于對話框的MFC程序測試DLL,此時(shí)在工程中包含上面這個(gè)頭文件,不用在聲明導(dǎo)入的類和函數(shù)了。

三、   使用模塊定義文件和動(dòng)態(tài)加載動(dòng)態(tài)鏈接庫

1.  新建dlltest.dll工程,加入一源文件dlltest.cpp,包含add和subtract兩個(gè)函數(shù)如下:

int add(int a,int b) { return a+b; } int subtract(int a,int b) { return a-b; }

2.       使用模塊定義文件防止文件名改變,在目錄中新建dlltest.def文件,增加到工程。

LIBRARY dlltest
EXPORTS
add
subtract

注:LIBRARYEXPORTS的用法參照MSDN.

3.       編譯后用dumpbin查看到函數(shù)名沒有改變。

4.       用動(dòng)態(tài)加載的方法來調(diào)用dll文件。

void CCalldllDlg::OnAdd() { // TODO: Add your control notification handler code here HINSTANCE hInst; hInst=LoadLibrary('dlltest.dll'); typedef int (/*_stdcall*/ *ADDPROC)(int a,int b); //ADDPROC Add=(ADDPROC)GetProcAddress(hInst,'?add@@YAHHH@Z'); //ADDPROC Add=(ADDPROC)GetProcAddress(hInst,MAKEINTRESOURCE(1)); ADDPROC Add=(ADDPROC)GetProcAddress(hInst,'add'); if(!Add) { MessageBox('獲取函數(shù)地址失??!'); return; } CString str; str.Format('2+3=%d',Add(2,3)); MessageBox(str); FreeLibrary(hInst); }

注意:

1.       這里調(diào)用的GetProcAddress函數(shù)中的第二個(gè)參數(shù)是動(dòng)態(tài)鏈接庫中導(dǎo)出的函數(shù)名,如果動(dòng)態(tài)鏈接庫中沒有用模塊定義文件防止函數(shù)名粉碎,則要用注釋掉的GetProcAddress(hInst,'?add@@YAHHH@Z'),另外也可按序號訪問GetProcAddress(hInst,MAKEINTRESOURCE(1))

2.       使用模塊定義文件后,如果改變調(diào)用約定為_stdcall,函數(shù)名也不會(huì)被改變,但如果加上_stdcall定義函數(shù),調(diào)用時(shí)也需要加上_stdcall,否則會(huì)出錯(cuò)。

3.       動(dòng)態(tài)加載不需要將文件dlltest.lib拷貝到此工程目錄下,并在Project Settings的Link標(biāo)簽下添加此文件,只需將dll文件拷貝到工程目錄下即可,并且通過dumpbin -imports calldll.exe查看它的輸入信息時(shí),可以看到它并沒有加載dlltest.dll。

4.       動(dòng)態(tài)加載的好處是需要時(shí)再加載,可以提高執(zhí)行的效率。當(dāng)不使用DLL時(shí),調(diào)用FreeLibrary減少DLL的使用計(jì)數(shù),釋放DLL資源,減少系統(tǒng)負(fù)擔(dān)。

5.       不使用模塊定義文件,也可用extern 'C'使函數(shù)名保持不變,如#define DLL1_API extern 'C' _declspec(dllexport),但它只能導(dǎo)出全局函數(shù),不能導(dǎo)出類的成員函數(shù),并且如果調(diào)用約定被改成了別的方式,此時(shí)函數(shù)名也被改變,所以一般不用這種方式。

    本站是提供個(gè)人知識管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多

    欧美日韩久久精品一区二区| 九九热这里有精品20| 在线中文字幕亚洲欧美一区| 99国产高清不卡视频| 欧美日本道一区二区三区| 日韩偷拍精品一区二区三区| 日韩欧美三级中文字幕| 中文字幕乱码免费人妻av| 国产永久免费高清在线精品| 99久久精品国产日本| 亚洲最新的黄色录像在线| 亚洲av日韩一区二区三区四区| 亚洲一区二区三区国产| 大香蕉精品视频一区二区| 字幕日本欧美一区二区| 日韩色婷婷综合在线观看| 国产精品欧美一区二区三区不卡| 精品al亚洲麻豆一区| 91福利免费一区二区三区| 欧美亚洲三级视频在线观看| 日本精品理论在线观看| 国产老熟女乱子人伦视频| 狠色婷婷久久一区二区三区| 国产精品香蕉在线的人| 美女被啪的视频在线观看| 在线免费视频你懂的观看| 中文字幕高清不卡一区| 可以在线看的欧美黄片| 国产欧美日韩在线一区二区| 亚洲中文字幕高清视频在线观看 | 国产精品熟女在线视频| 亚洲国产精品一区二区| 99久久国产精品成人观看| 精品人妻一区二区三区四区久久| 午夜资源在线观看免费高清| 视频一区二区三区自拍偷| 日本精品理论在线观看| 九九久久精品久久久精品| 麻豆印象传媒在线观看| 欧美一区二区三区喷汁尤物| 色婷婷亚洲精品综合网|