青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

白駒過隙
學而不思則罔,思而不學則怠
posts - 4,  comments - 3,  trackbacks - 0

?? 還有一種方法可以顯式導出類成員函數,就是采用虛函數表的方法。 COM 就是這樣做的。當在類中聲明一組虛函數的時候, 編譯器會創建一個虛函數表,將各虛函數的地址按聲明的順序放入其中。當一個類對象被創建時,它的前四個字節是一個指針,指向這個虛函數表。所以,修改以上的代碼:

//CTry.h

??? virtual void print() ; // 將這個成員函數聲明為虛函數

TRY_API CTry* createObject() ; // 聲明一個全局函數,創建一個 Ctry 對象的實例

//CTry.cpp

CTry *createObject()

{

??? return new CTry() ;

}

?

在測試工程中,顯式導出該全局函數,并通過它調用類成員函數。

typedef CTry* (*Fn_FunType)() ;

Fn_FunType pFun=(Fn_FunType)::GetProcAddress(hInstance ,"?createObject@@YAPAVCTry@@XZ") ;

CTry * pTry = pFun() ;

pTry ->print() ;

delete pTry ;


?? 這個方法雖然同樣能達到顯式導出類成員函數的目的。但是上面的方法有個缺點,就是在DLLnew 出來的對象,卻要放到客戶端釋放。因為客戶端并不知道DLL中的實現方法,很可能會不知道釋放這個對象,從而造成內存泄露。<<Effiective C++>>中明文規定禁止這樣做。

?

? 現在要找一個方法可以把回收內存的任務交 DLL 自己來處理。有沒有這樣一個方法呢?當然有,它就是引用計數。引用計數是一個簡單的垃圾回收機制,它的原理很簡單,組件內部維護著一個引用計數的數值,當用戶從組件取得一個接口時,該數值 +1 ,當用戶使用完這個接口,并釋放該接口時,該數值 -1 ,當該數值為 0 時,組件將自己從內存中刪除。下面是采用了引用計數的 DLL 實現方法。


#ifdef?TRY_EXPORTS
#define ?TRY_API?__declspec(dllexport)
#else
#define ?TRY_API?__declspec(dllimport)
#endif
#include?
< iostream >
using ? namespace ?std;

// ?此類是從?Try.dll?導出的
class ??CTry? {
public :
????friend?TRY_API?CTry
* ?createObject()?;

????
virtual ?? void ?print()?;

????
virtual ? void ?addRef()?;

????
virtual ? void ?removeRef()?;
protected :
????
int ?refCount?;

????
// 不允許通過構造函數初始化對象
????CTry( void )?;
????
????
virtual ? ~ CTry()?;


????
// 不允許相互賦值,這里面細節太多,懶得去分析:D
????CTry(CTry? & ths)?;

????CTry
* ? operator = ?( const ?CTry & ?ths?)?;
????
}
;

extern ?TRY_API? int ?nTry;

TRY_API?
int ?fnTry( void );
?
TRY_API?CTry
* ?createObject()?;

// ?Try.cpp?:?定義?DLL?應用程序的入口點。
//

#include?
" stdafx.h "
#include?
" Try.h "


#ifdef?_MANAGED
#pragma?managed(push,?off)
#endif

BOOL?APIENTRY?DllMain(?HMODULE?hModule,
???????????????????????DWORD??ul_reason_for_call,
???????????????????????LPVOID?lpReserved
?????????????????????)
{
????
switch ?(ul_reason_for_call)
????
{
????
case ?DLL_PROCESS_ATTACH:
????
case ?DLL_THREAD_ATTACH:
????
case ?DLL_THREAD_DETACH:
????
case ?DLL_PROCESS_DETACH:
????????
break ;
????}

????
return ?TRUE;
}


#ifdef?_MANAGED
#pragma?managed(pop)
#endif

// ?這是導出變量的一個示例
TRY_API? int ?nTry? = ? 0 ;

// ?這是導出函數的一個示例。
TRY_API? int ?fnTry( void )
{
????
return ? 42 ;
}


// ?這是已導出類的構造函數。
// ?有關類定義的信息,請參閱?Try.h

void ?CTry::print()
{
????cout
<< " CTry " << endl;
}


?CTry?
* createObject()
?
{
?????CTry?
* pTry? = ? new ?CTry()?;
?????pTry
-> addRef()?;
?????
return ?pTry?;
?}


?
void ?CTry::removeRef()
?
{
?????
if ?( -- refCount? == ? 0 )
?????
{
?????????delete?
this ?; // 刪除自己
?????}

?}


?
void ?CTry::addRef()
?
{
?????
++ refCount?;
?}


?CTry::CTry()
?
{
?????refCount?
= ? 0 ?;
?}


?CTry::
~ CTry()
?
{

?}

?CTry::CTry(CTry?
& ths)
?
{

?}


?CTry?
* CTry:: operator ? = ( const ?CTry? & ths)
?
{
?????
return ?NULL;
?}

?

? 上面的方法中,用戶不能通過構造函數來實例化一個對象,必須通過 createObject 接口才能實例化對象,當用戶使用完這個對象時必須調用 removeRef() 接口。代碼如下:

#include? " stdafx.h "
#include?
< iostream >
#include?
" Try.h "
using ? namespace ?std;

typedef?CTry
* ?( * Fn_FunType)()?;

int ?main()
{

????HINSTANCE?hInstance?
= ? 0 ;
????hInstance?
= ?LoadLibrary( " Try.dll " )?;
????
if ?(hInstance)
????
{
????????Fn_FunType?pFun?
= ?(Fn_FunType)::GetProcAddress(hInstance?, " ?createObject@@YAPAVCTry@@XZ " )?;

????????
if ?(pFun)
????????
{
????????????
// (pTry->*pFun)()?;
????????????CTry * ?pTry? = ?pFun()?;
????????????pTry
-> print()?;
????????????pTry
-> removeRef();
????????}

????}

????system(
" pause " )?;
????
return ? 0 ?;
}



? 當然上面只是我為了方便測試而寫的一個簡單的例子,還不完善。引用計數還有很多細節和注意事項。具體請看《more effective c++》第29項。

?

關于名字修飾約定

?

?? 前面代碼我都是通過編譯器中的修飾名來調用相應的函數的,修飾名是編譯器在編譯函數定義或者原型時生成的字符串。比如 "?createObject@@YAPAVCTry@@XZ" 就是 CTry::createObject 的修飾名。

名字修飾約定隨調用約定和編譯種類 (C C++) 的不同而變化。函數名修飾約定隨編譯種類和調用約定的不同而不同,下面分別說明。

A 、 C 編譯時函數名修飾約定規則:

__stdcall 調用約定在輸出函數名前加上一個下劃線前綴,后面加上一個 "@" 符號和其參數的字節數,格式為 _functionname@number 。

__cdecl 調用約定僅在輸出函數名前加上一個下劃線前綴,格式為 _functionname

__fastcall 調用約定在輸出函數名前加上一個 "@" 符號,后面也是一個 "@" 符號和其參數的字節數,格式為 @functionname@number 。

它們均不改變輸出函數名中的字符大小寫,這和 PASCAL 調用約定不同, PASCAL 約定輸出的函數名無任何修飾且全部大寫。

B 、 C++ 編譯時函數名修飾約定規則:

__stdcall 調用約定:

1 、以 "?" 標識函數名的開始,后跟函數名;

2 、函數名后面以 "@@YG" 標識參數表的開始,后跟參數表;

3 、參數表以代號表示:

X--void

D--char

E--unsigned char ,

F--short

H--int

I--unsigned int ,

J--long ,

K--unsigned long

M--float

N--double ,

_N--bool

....

PA-- 表示指針,后面的代號表明指針類型,如果相同類型的指針連續出現,以 "0" 代替,一個 "0" 代表一次重復;

4 、參數表的第一項為該函數的返回值類型,其后依次為參數的數據類型 , 指針標識在其所指數據類型前;

5 、參數表后以 "@Z" 標識整個名字的結束,如果該函數無參數,則以 "Z" 標識結束。

其格式為 "?functionname@@YG*****@Z" "?functionname@@YG*XZ" ,例如

????????? int Test1 char *var1,unsigned long ----- ?Test1@@YGHPADK@Z

????????? void Test2 () ?????????????????????? ----- ?Test2@@YGXXZ

?

__cdecl 調用約定:

規則同上面的 _stdcall 調用約定,只是參數表的開始標識由上面的 "@@YG" 變為 "@@YA" 。

__fastcall 調用約定:

規則同上面的 _stdcall 調用約定,只是參數表的開始標識由上面的 "@@YG" 變為 "@@YI" VC++ 對函數的省缺聲明是 "__cedcl", 將只能被 C/C++ 調用 .

?

?? 通常我們希望我們的 DLL 中的導出函數名能夠更易被識別(用戶使用才會更方便),也就是說 DLL 應該編譯出無修飾的 C 函數名,而不復雜的修飾名。所以當使用 C++ 文件來創建 DLL 時應該使用 extern “c” 來修飾導出函數和變量。實際上 VS 編譯器已經為我們準備了一個宏 EXTERN_C 用來代替 extern “c” 。修改以上的代碼如下:

EXTERN_C TRY_API int nTry;

EXTERN_C TRY_API int fnTry(void);

生成 DLL ,用 depens 工具查看,他們已經變成了如下模樣:

?

這樣在客戶端就可以通過函數名去調用它們。但是 EXTERN_C 宏卻沒辦法修飾類成員函數,

如果像全局函數那樣修飾類成員函數,編譯無法通過。用 .DEF 文件可以解決這個問題。

?

關于 .def 文件

模塊定義 (.def) 文件是包含一個或多個描述 DLL 各種屬性的 Module 語句的文本文件。

def 文件包含下列模塊定義語句:

1. 文件中的第一個語句必須是 LIBRARY 語句。此語句將 .def 文件標識為屬于 DLL 。 LIBRARY 語句的后面是 DLL 的名稱。鏈接器將此名稱放到 DLL 的導入庫中。

2. ?EXPORTS 語句列出被導出函數的名字;將要輸出的函數修飾名羅列在 EXPORTS 之下,這個名字必須與定義函數的名字完全一致,如此就得到一個沒有任何修飾的函數名了。

3.? 可以使用 DESCRIPTION 語句描述 DLL 的用途 ( 此句可選 ) ;

4.?? ";" 對一行進行注釋 ( 可選 ) 。

?

創建一 .DEF 文件,命名為 export.def ,用來修飾 CTry::print 函數,如下:

LIBRARY??? "Try"

EXPORTS

print????? =????? ?print@CTry@@UAEXXZ? PRIVATE

?

DLL 工程屬性 -> 鏈接器 -> 輸入 -> 模塊定義文件中將 export.def 添加進去。這樣就可以直接通過函數名來顯式調用類成員函數了。下面是 DLL depens 工具中顯示的情況。

?

參考資料:

windows 核心編程》

programming windows

《微軟 DLL 專題》

posted on 2009-03-08 17:01 隙中駒 閱讀(548) 評論(1)  編輯 收藏 引用

FeedBack:
# re: DLL學習筆記 3
2009-03-12 09:32 | guest
圖片的路徑是“e:/1.bmp”,你本地應該可以顯示,但是其他地方都看不到圖了。
請修改圖片鏈接。  回復  更多評論
  

只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理



<2025年11月>
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

常用鏈接

留言簿(2)

隨筆檔案(4)

文章分類(1)

文章檔案(1)

友情鏈接

最新隨筆

搜索

  •  

最新評論

  • 1.?re: DLL學習筆記 3
  • 圖片的路徑是“e:/1.bmp”,你本地應該可以顯示,但是其他地方都看不到圖了。
    請修改圖片鏈接。
  • --guest
  • 2.?re: DLL學習筆記2
  • 圖片的路徑是“e:/1.bmp”,你本地應該可以顯示,但是其他地方都看不到圖了。
    請修改下圖片鏈接。
  • --guest
  • 3.?re: DLL學習筆記1
  • 好,我跟著你一起學習
  • --bk

閱讀排行榜

評論排行榜

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久久欧美精品| 亚洲高清中文字幕| 亚洲一级黄色片| 美女国内精品自产拍在线播放| 亚洲肉体裸体xxxx137| 久久亚洲国产精品日日av夜夜| 国产精品色婷婷久久58| 一区二区免费在线观看| 亚洲黄色一区| 欧美国产亚洲精品久久久8v| 亚洲国产清纯| 免费日韩视频| 麻豆国产精品一区二区三区 | 性色av一区二区三区| 欧美视频一区二区| 亚洲欧美日本国产专区一区| 99精品欧美一区二区三区综合在线| 欧美激情aaaa| 亚洲欧美中文在线视频| 久久久亚洲人| 日韩网站在线看片你懂的| 亚洲伦理在线| 亚洲黄色在线看| 老鸭窝毛片一区二区三区| 在线成人亚洲| 欧美激情中文字幕一区二区| 欧美99久久| 日韩视频一区二区三区| 亚洲理论在线观看| 国产精品毛片a∨一区二区三区|国 | 最新日韩在线| 亚洲免费观看在线观看| 欧美日韩中文另类| 香蕉成人啪国产精品视频综合网| 亚洲一区二区在线免费观看视频| 欧美在线你懂的| 欧美在线看片| 午夜在线精品偷拍| 影院欧美亚洲| 亚洲精品中文字幕在线| 国产精品久久午夜| 久久婷婷国产麻豆91天堂| 老司机午夜精品视频| 中文亚洲字幕| 久久精品国产精品亚洲精品| 亚洲激情欧美激情| 亚洲一二三区精品| 一色屋精品视频在线观看网站| 亚洲欧洲日本在线| 国产乱码精品一区二区三区忘忧草 | 性久久久久久久| 久久婷婷久久一区二区三区| 一本色道久久综合亚洲精品高清 | 国产精品亚洲精品| 亚洲成色www8888| 国产九九精品视频| 亚洲欧洲精品天堂一级| 国产偷国产偷精品高清尤物| 亚洲国产你懂的| 国外视频精品毛片| 国产精品99久久不卡二区| 亚洲国产另类久久精品| 国产精品入口夜色视频大尺度| 99热免费精品在线观看| 国产视频一区免费看| 91久久精品一区二区别| 国内成人自拍视频| 99精品视频免费| 亚洲国产日韩在线一区模特| 午夜激情综合网| 一区二区三区精品久久久| 久久久久久亚洲精品中文字幕| 亚洲欧美激情视频| 欧美精品自拍| 亚洲国产福利在线| 伊大人香蕉综合8在线视| 亚洲欧美国产另类| 亚洲自拍电影| 欧美视频在线观看一区二区| 欧美韩日视频| 黄色成人片子| 欧美在线黄色| 久久精品在线| 国产欧美日韩精品专区| 在线亚洲欧美视频| 亚洲制服av| 国产精品国产三级国产普通话99| 亚洲国产免费| 亚洲精选大片| 欧美激情精品| 亚洲精品激情| 国产精品99久久久久久人| 欧美精品免费在线| 亚洲人成亚洲人成在线观看| 亚洲精品孕妇| 欧美日韩国产bt| 99精品国产高清一区二区| 中国女人久久久| 国产精品九九久久久久久久| 亚洲私人影院| 久久se精品一区二区| 国产有码在线一区二区视频| 久久精品卡一| 欧美激情在线| 亚洲午夜激情免费视频| 国产精品yjizz| 午夜精品福利电影| 裸体歌舞表演一区二区| 亚洲国产日韩欧美| 欧美精品一区二区三区高清aⅴ| 日韩亚洲不卡在线| 欧美一级视频免费在线观看| 国内不卡一区二区三区| 欧美凹凸一区二区三区视频| 亚洲欧洲精品天堂一级| 亚洲欧美日本日韩| 狠狠色噜噜狠狠狠狠色吗综合| 久热爱精品视频线路一| 亚洲精品影视在线观看| 欧美一区二区视频在线观看| 在线观看的日韩av| 欧美日韩国产另类不卡| 亚洲在线观看免费视频| 欧美sm视频| 亚洲一区激情| 在线观看视频亚洲| 国产精品久久久久久福利一牛影视| 欧美一区亚洲| avtt综合网| 免费观看日韩av| 一区二区三区日韩欧美| 国内在线观看一区二区三区| 欧美激情综合在线| 久久青草久久| 国产精品豆花视频| 久久久久成人精品免费播放动漫| 亚洲欧洲在线一区| 久久九九精品| 亚洲午夜在线观看| 亚洲国产成人不卡| 国产精品夜夜夜| 欧美福利视频网站| 欧美伊人久久| 亚洲影院免费观看| 亚洲人成亚洲人成在线观看| 久久亚洲风情| 午夜精品免费| 日韩小视频在线观看| 国内久久视频| 国产精品一区2区| 欧美日韩在线精品| 欧美第一黄网免费网站| 久久精品日产第一区二区| 中文在线资源观看视频网站免费不卡| 欧美aaaaaaaa牛牛影院| 欧美中文字幕在线| 亚洲免费伊人电影在线观看av| 亚洲国产成人不卡| 在线观看欧美亚洲| 国内免费精品永久在线视频| 国产精品欧美日韩| 欧美视频免费在线| 欧美亚洲成人精品| 欧美无砖砖区免费| 欧美日韩中国免费专区在线看| 欧美激情一区二区三区 | 伊人久久婷婷色综合98网| 国产精品免费看久久久香蕉| 欧美色区777第一页| 欧美日韩视频不卡| 欧美日韩成人在线| 欧美日韩精品三区| 欧美日韩国产综合网| 欧美精品久久久久a| 欧美精品成人| 欧美日韩福利视频| 欧美特黄视频| 国产精品美女久久久浪潮软件| 欧美无乱码久久久免费午夜一区| 欧美日韩一区二区在线视频 | 国产午夜精品视频免费不卡69堂| 国产精品毛片高清在线完整版| 国产精品二区影院| 国产欧美日韩综合一区在线观看| 国产精品亚洲网站| 国产一区二区久久久| 狠狠色狠色综合曰曰| 亚洲国产成人在线播放| 91久久精品国产91久久| 亚洲靠逼com| 亚洲一二三区在线| 性欧美1819性猛交| 久久久精品网| 欧美国产在线观看| 99国产一区| 欧美在线视频一区二区| 久久久久久亚洲精品不卡4k岛国| 欧美成人精品在线| 国产精品视频区| 悠悠资源网久久精品|