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

dll基礎

Posted on 2008-07-29 16:08 RichardHe 閱讀(321) 評論(0)  編輯 收藏 引用 所屬分類: [再轉]
自從微軟推出第一個版本的Windows操作系統以來,動態鏈接庫(DLL)一直是Wind
ows操作系統的基礎。
動態鏈接庫通常都不能直接運行,也不能接收消息。它們是一些獨立的文件,其中
包含能被可執行程序或其它DLL調用來完成某項工作的函數。只有在其它模塊調用動
態鏈接庫中的函數時,它才發揮作用。
Windows API中的所有函數都包含在DLL中。其中有3個最重要的DLL,Kernel32.dll
,它包含用于管理內存、進程和線程的各個函數;User32.dll,它包含用于執行用
戶界面任務(如窗口的創建和消息的傳送)的各個函數;GDI32.dll,它包含用于畫
圖和顯示文本的各個函數。
           靜態庫和動態庫
靜態庫:函數和數據被編譯進一個二進制文件(通常擴展名為.LIB)。在使用靜態庫
的情況下,在編譯鏈接可執行文件時,鏈接器從庫中復制這些函數和數據并把它們
和應用程序的其它模塊組合起來創建最終的可執行文件(.EXE文件)。
在使用動態庫的時候,往往提供兩個文件:一個引入庫和一個DLL。引入庫包含被D
LL導出的函數和變量的符號名,DLL包含實際的函數和數據。在編譯鏈接可執行文件
時,只需要鏈接引入庫,DLL中的函數代碼和數據并不復制到可執行文件中,在運行
的時候,再去加載DLL,訪問DLL中導出的函數。
使用動態鏈接庫的好處
可以采用多種編程語言來編寫。
增強產品的功能。
提供二次開發的平臺。
簡化項目管理。
可以節省磁盤空間和內存。
有助于資源的共享。
有助于實現應用程序的本地化。
動態鏈接庫被多個進程訪問
動態鏈接庫加載的兩種方式
預備知識
::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::
::::
進程的虛擬地址空間:
 在32為系統中,系統為沒個進程分配2^32的地址空間
具體可參看《windows核心編程》
預處理命令:
沒有什么可以說的了
看看代碼就明白了!!
環境變量:(環境變量的概念我就不介紹了,具體的可以參看windows 核心編程,
上面有很詳細的說明)把DLL放到當前任意的環境變量中就可以加載
定義函數指針
格式:typedef  int (*proc)(int a,int b);
注意:proc是一個函數指針類型而不是一個變量
然后我們可以用這個指針類型去定義變量
Proc myproc;這里的myproc就是一個指針變量
要是實在無聊 內心空虛 沒事可做的話 可以去這個網站看看函數的指針http://uf
o.tyedu.com/study/programmer/language_C/200412/1472.html  
函數的調用約定(可以不必了解,但是理解后可以讓你理解DLL的調用更為深刻)
函數的調用約定:函數調用約定是函數調用者和被調用的函數體之間關于參數傳遞
、返回值傳遞、堆棧清除、寄存器使用的一種約定;
   它是需要二進制級別兼容的強約定,函數調用者和函數體如果使用不同的調用約
定,將可能造成程序執行錯誤,必須把它看作是函數聲明的一部分;
常見的函數調用約定:
VC6中的函數調用約定:
       調用約定        堆棧清除    參數傳遞
       __cdecl         調用者      從右到左,通過堆棧傳遞
       __stdcall       函數體      從右到左,通過堆棧傳遞
       __fastcall      函數體      從右到左,優先使用寄存器(ECX,EDX),然后
使用堆棧
       thiscall        函數體      this指針默認通過ECX傳遞,其它參數從右
到左入棧
__cdecl是C\C++的默認調用約定; VC的調用約定中并沒有thiscall這個關鍵字,它是
類成員函數默認調用約定;
C\C++中的main(或wmain)函數的調用約定必須是__cdecl,不允許更改;
默認調用約定一般能夠通過編譯器設置進行更改,如果你的代碼依賴于調用約定,請
明確指出需要使用的調用約定;
常見的函數調用約定中,只有cdecl約定需要調用者來清除堆棧;
C\C++中的函數支持參數數目不定的參數列表,比如printf函數;由于函數體不知道調
用者在堆棧中壓入了多少參數,
所以函數體不能方便的知道應該怎樣清除堆棧,那么最好的辦法就是把清除堆棧的責
任交給調用者;
這應該就是cdecl調用約定存在的原因吧;
VB一般使用的是stdcall調用約定;(ps:有更強的保證嗎)
Windows的API中,一般使用的是stdcall約定;(ps: 有更強的保證嗎)
建議在不同語言間的調用中(如DLL)最好采用stdcall調用約定,因為它在語言間兼容
性支持最好;
三:函數返回值傳遞方式
  其實,返回值的傳遞從處理上也可以想象為函數調用的一個out形參數; 函數返
回值傳遞方式也是函數調用約定的一部分;
  有返回值的函數返回時:一般int、指針等32bit數據值(包括32bit結構)通過ea
x傳遞,(bool,char通過al傳遞,short通過 ax傳遞),特別的__int64等64bit結構(
struct) 通過edx,eax兩個寄存器來傳遞(同理:32bit整形在16bit環境中通過dx,a
x傳遞); 其他大小的結構(struct)返回時把其地址通過eax返回;(所以返回值類型
不是1,2,4,8byte時,效率可能比較差)
  參數和返回值傳遞中,引用方式的類型可以看作與傳遞指針方式相同;
  float\double(包括Delphi中的extended)都是通過浮點寄存器st(0)返回;

具體的分析參看:http://blog.csdn.net/avalonbbs/archive/2004/12/25/229300
.aspx
::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::
:::::::




隱式鏈接
本文現在對隱式鏈接不作具體的說明,只是做一個大概的介紹(下次再做具體的說
明).當進程運行的時候,所有的相關的DLL都被加載到內存,然后映射到進程的地
址空間,當一個進程要調用很多個DLL的時候,這種方法就顯得特別浪費內存,所以
在加載很多個DLL的時候,最好用顯示加載的方式
在調用DLL里面的函數時候
要用extern 聲明是外部變量
比如 extern int add(int num1,int num2);
但是還應該注意的就是:在編譯DLL時,要把編譯的LIB文件放到執行文件的目錄下
,并且在編譯執行文件的時候要連接LIB文件。
在寫DLL的時候要導出的函數也就是在能被外部程序調用的函數前面加上
一般大型項目在開發DLL中,要進行預定義聲明的

====================================
==
在定義DLL的時候要定義導出函數就要在該函數前面加__declspec(DLLexport)時,
C++編譯器為了支持函數的重載會進行函數名字改編,當可執行模塊執行該函數時由
于找不到該函數的名字,于是調用就會出現錯誤!當使用extern “C”時就可以告
訴編譯器不必修改函數名和變量名。這樣就可以用C++或C編譯器程序調用該函數。

以上操作只有在VC++創建的的可執行模塊來調用該DLL,如果使用其他的編譯器的模
塊來調用該DLL,就需要執行一些額外的操作。
C編譯在進行編譯的時候也會進行名字的改編,當函數使用_stdcall(WINAPI)調用
規則時,MS編譯器就會改編函數的名稱。
比如:__declspec(DLLexport)  LONG __stdcall  Proc(int a ,int b);
編譯器會改編為__Proc@8
因此 當非C++或非C編譯器調用該DLL中的函數Proc時,就會出現找不到函數的情況

這樣我們就可以定義DEF文件來解決,并且在DEF文件加上下面的EXPORTS:
EXPORTS
       Proc
Def模塊執行原理:當連接程序分析這個DEF文件時,它發現Proc和__Proc@8都被輸
出,由于這兩個函數是相互匹配的,因此連接程序使用Proc來輸出該函數,根本不
使用__Proc@8來輸出函數名
====================================
===

                




下面是def的具體使用方法

------------------------------------------------------------------------
----------------------------------------------模塊定義文件(.DEF)是一個或
多個用于描述DLL屬性的模塊語句組成的文本文件,每個DEF文件至少必須包含以下
模塊定義語句:
* 第一個語句必須是LIBRARY語句,指出DLL的名字;
* EXPORTS語句列出被導出函數的名字;將要輸出的函數修飾名羅列在EXPORTS之下
,這
個名字必須與定義函數的名字完全一致,如此就得到一個沒有任何修飾的函數名了

* 可以使用DESCRIPTION語句描述DLL的用途(此句可選);
* ";"對一行進行注釋(可選)。
------------------------------------------------------------------------
----------------------------------------------


////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////
dlltest.h
#ifdef DLL1_API
#else
#define DLL1_API extern "C" _declspec(dllimport)
#endif

DLL1_API int _stdcall add(int a,int b);
DLL1_API int _stdcall subtract(int a,int b);
////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////


\\\\\\\\\\\\\\\\\\
\\\\\\\\\\\\\\\\\\//
dlltest.cpp
#define DLL1_API extern "C" _declspec(dllexport)
#include "Dll1.h"
#include <stdio.h>
int _stdcall add(int a,int b)
{
    return a+b;
}

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

////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////
// def文件
LIBRARY dlltest
EXPORTS
add
subtract
////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////

有了上面的那些文件之后就可以在如何地方調用這些函數了

void CDllTestDlg::OnBtnSubtract()
{
    // TODO: Add your control notification handler code here
    CString str;
    str.Format("5-3=%d",subtract(5,3));
    MessageBox(str);
}

void CDllTestDlg::OnBtnOutput()
{
    // TODO: Add your control notification handler code here
    Point pt;
    pt.output(5,3);
}下面具體介紹顯示加載
顯示加載
VC++編譯器在編譯DLL的時候函數會發生名字改編;主要在非C++環境中就不能識別
該函數了,所以這里應該定義模塊文件類型DEF,主要就方便了非C++程序可以調用
該DLL里面的函數
再使用顯示加載前必須要注意的是名字的改編問題,因為再動態加載中名字改編后
在加載就得不原來的函數名字了,這樣加載就會失敗。但是可以用另外一種方法加
載:MSDN上對GetProAddress中的第二個參數是這樣說明的Pointer to a null-ter
minated string that specifies the function or variable name, or the func
tion's ordinal value.也就是說可以使用函數的序號來調用該函數,具體使用方法
是ProcAdd = (MYPROC) GetProcAddress(hinstLib, MakeIntResource(i)); (i代表
函數在DLL中的序號,可以用DUMPBIN工具查看),但是一般的都不用這種轉換序號的
方式來取得函數的地址,因為這樣非常的不直觀!下面就用模塊定義文件(DEF)來
避免DLL中函數的名字的改編問題





顯示加載DLL
//MSDN上的對DLL進程顯示加載的DEMO
Using Run-Time Dynamic Linking
You can use the same DLL in both load-time and run-time dynamic linking.
The following example uses the LoadLibrary function to get a handle to
the Myputs DLL (see Creating a Simple Dynamic-Link Library). If LoadLibr
ary succeeds, the program uses the returned handle in the GetProcAddress
function to get the address of the DLL's myPuts function. After calling
the DLL function, the program calls the FreeLibrary function to unload
the DLL.
Because the program uses run-time dynamic linking, it is not necessary t
o link the module with an import library for the DLL.
This example illustrates an important difference between run-time and lo
ad-time dynamic linking. If the DLL is not available, the application us
ing load-time dynamic linking must simply terminate. The run-time dynami
c linking example, however, can respond to the error.
// A simple program that uses LoadLibrary and
// GetProcAddress to access myPuts from Myputs.dll.

#include <stdio.h>
#include <windows.h>
typedef int (*MYPROC)(LPTSTR);
VOID main(VOID)
{
   HINSTANCE hinstLib;
   MYPROC ProcAdd;
   BOOL fFreeResult, fRunTimeLinkSuccess = FALSE;
 // Get a handle to the DLL module.
hinstLib = LoadLibrary(TEXT("DllTest"));
// If the handle is valid, try to get the function address.
if (hinstLib != NULL)
   {
       ProcAdd = (MYPROC) GetProcAddress(hinstLib, TEXT("Proc"));
// If the function address is valid, call the function.
 if (NULL != ProcAdd)
       {
           fRunTimeLinkSuccess = TRUE;
           (ProcAdd) (TEXT("Message via DLL function\n"));
       }
 // Free the DLL module.
fFreeResult = FreeLibrary(hinstLib);
   }
 // If unable to call the DLL function, use an alternative.
if (! fRunTimeLinkSuccess)
      printf("Message via alternative method\n");
}

對以上的幾個函數作一些必要的說明:
LoadLibrary:加載指定的DLL,加載方式是先在當前目錄中查找,如果找不到再再
環境變量目錄下查找;
還是看MSDN上的說明
The LoadLibrary function maps the specified executable module into the a
ddress space of the calling process.
HMODULE LoadLibrary(
 LPCTSTR lpFileName
);
Parameters
lpFileName
[in] Pointer to a null-terminated string that names the executable modul
e (either a .dll or .exe file). The name specified is the file name of t
he module and is not related to the name stored in the library module it
self, as specified by the LIBRARY keyword in the module-definition (.def
) file.

GetProcAddress:是取得已知的DLL中的函數,返回指定函數的地址
MSDN上的說明
This function returns the address of the specified exported DLL function
.
FARPROC GetProcAddress(
 HMODULE hModule,
 LPCWSTR lpProcName
);
Parameters
hModule
[in] Handle to the DLL module that contains the function.
The LoadLibrary or GetModuleHandle function returns this handle.
lpProcName
[out] Pointer to a null-terminated string containing the function name,
or specifies the function's ordinal value.
If this parameter is an ordinal value, it must be in the low-order word;
the high-order word must be zero.
The lpProcName parameter must be in Unicode.
Remark:
The GetProcAddress function is used to retrieve addresses of exported fu
nctions in DLLs.
The spelling and case of the function name pointed to by lpProcName must
be identical to that in the EXPORTS statement of the source DLL's modul
e-definition (.def) file.
The exported names of Win32 APIs might differ from the names you use whe
n calling these functions in your code. This difference is hidden by mac
ros used in the SDK header files.

posts - 94, comments - 138, trackbacks - 0, articles - 94

Copyright © RichardHe

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美激情在线狂野欧美精品| 久久久国产精品一区| 欧美视频一区二区三区在线观看| 欧美国产日韩一区二区| 免费欧美日韩| 欧美.www| 亚洲青色在线| 亚洲国产精品一区二区三区| 亚洲国产另类精品专区| 亚洲精品中文字幕女同| 亚洲视屏在线播放| 久久精品国语| 欧美久久九九| 国产日韩欧美精品| 亚洲日本aⅴ片在线观看香蕉| 夜夜精品视频一区二区| 亚洲欧美日韩第一区| 久久夜色精品国产噜噜av| 亚洲成色999久久网站| 一本一本大道香蕉久在线精品| 亚洲欧美99| 欧美成人免费小视频| 国产精品久久久久久久一区探花| 好看不卡的中文字幕| 99成人免费视频| 久久久久久香蕉网| 洋洋av久久久久久久一区| 久久精品国语| 国产精品久久久久一区二区三区| 在线不卡免费欧美| 午夜精品久久久久久久男人的天堂| 狂野欧美性猛交xxxx巴西| 欧美成人精品h版在线观看| 亚洲国产清纯| 欧美在线亚洲一区| 国产精品超碰97尤物18| 亚洲精品免费电影| 久久噜噜亚洲综合| 国产精品一二一区| 亚洲精选视频免费看| 久久免费视频网| 亚洲自啪免费| 国产精品ⅴa在线观看h| 亚洲精品男同| 欧美成人自拍视频| 欧美一区二区视频在线观看| 欧美午夜电影在线观看| 亚洲精品一二三| 蜜桃久久精品乱码一区二区| 亚洲影院色在线观看免费| 欧美日韩不卡视频| 亚洲精品在线观| 亚洲电影免费| 欧美gay视频激情| 亚洲国产另类 国产精品国产免费| 久久精品亚洲一区二区三区浴池| 亚洲一区二区3| 国产精品久久久久久久久久尿| 亚洲美女精品久久| 亚洲国产婷婷| 欧美国产精品久久| 亚洲人人精品| 亚洲欧洲精品一区二区三区 | 欧美乱大交xxxxx| 亚洲人成网站在线播| 久久综合一区| 亚洲精品激情| 亚洲国产日日夜夜| 欧美日本一区二区三区| av不卡在线看| 在线亚洲观看| 国产情人节一区| 久久夜色精品一区| 久久人人97超碰国产公开结果| 国产在线观看91精品一区| 可以免费看不卡的av网站| 久久露脸国产精品| 亚洲国产综合在线| 亚洲乱码国产乱码精品精98午夜| 欧美三区在线观看| 欧美在线观看视频在线| 久久久久久久久久码影片| 亚洲日本一区二区三区| 亚洲美女视频在线免费观看| 国产精品欧美精品| 美女精品自拍一二三四| 欧美激情一区二区三区成人| 亚洲无线视频| 久久天堂成人| 亚洲一区二区三区涩| 久久黄色影院| 宅男噜噜噜66一区二区| 欧美在线看片| av成人毛片| 欧美一区二区在线观看| 亚洲日韩成人| 久久精品二区| 亚洲精品美女免费| 伊人色综合久久天天| 91久久久精品| 国产亚洲精品综合一区91| 欧美激情精品久久久久久黑人| 欧美天天综合网| 免费日韩av片| 国产伦理一区| 99成人免费视频| 亚洲电影第三页| 亚洲性图久久| 一本色道久久综合亚洲精品婷婷| 欧美一区二区三区免费观看视频| 日韩视频一区二区三区在线播放| 午夜欧美理论片| 亚洲视频视频在线| 老司机精品导航| 久久九九久精品国产免费直播| 欧美国产先锋| 欧美激情视频免费观看| 国产综合香蕉五月婷在线| 在线亚洲伦理| 日韩五码在线| 美女国内精品自产拍在线播放| 欧美在线一区二区三区| 欧美日韩一区视频| 亚洲国产你懂的| 亚洲国产精品激情在线观看 | 鲁大师成人一区二区三区| 亚洲欧美日韩综合aⅴ视频| 欧美黄色大片网站| 欧美激情第3页| 亚洲黄页一区| 伊大人香蕉综合8在线视| 亚洲视频在线看| 欧美日韩一区精品| 一区二区欧美在线观看| 一区二区免费在线视频| 欧美激情中文字幕乱码免费| 欧美国产日韩二区| 亚洲人成久久| 欧美高清在线视频| 亚洲人成网站777色婷婷| 亚洲精品无人区| 欧美日本三级| 亚洲丝袜av一区| 亚洲影院高清在线| 国产精品网站在线观看| 亚洲欧美日韩专区| 久久久久欧美精品| 亚洲大片一区二区三区| 欧美成人激情在线| aaa亚洲精品一二三区| 亚洲一区二区在线免费观看| 国产精品伦子伦免费视频| 亚洲欧美日韩国产综合精品二区 | 亚洲国产视频a| 99精品国产在热久久婷婷| 欧美三级欧美一级| 午夜在线精品偷拍| 久久在线播放| 日韩午夜电影av| 国产麻豆午夜三级精品| 久久精品女人天堂| 日韩视频二区| 欧美三级乱码| 久久久久久久一区| 久久精品九九| 亚洲九九精品| 久久精品一本久久99精品| 猫咪成人在线观看| 日韩一级二级三级| 国产美女精品视频免费观看| 久久久久久久久久久久久女国产乱 | 一区二区三区不卡视频在线观看| 欧美日韩一区成人| 欧美中文字幕视频| 亚洲高清视频一区| 欧美一级大片在线免费观看| 黄色成人免费观看| 欧美午夜视频网站| 美国十次了思思久久精品导航| 亚洲视频免费看| 欧美大片va欧美在线播放| 亚洲欧美激情在线视频| 亚洲国产一区二区三区在线播 | 亚洲国产综合91精品麻豆| 国产精品美女黄网| 欧美成人午夜| 久久不见久久见免费视频1| 亚洲伦理在线观看| 免费日韩av| 久久成人免费视频| 亚洲视频在线观看三级| 亚洲欧洲日本一区二区三区| 国产九九精品| 欧美少妇一区二区| 欧美va亚洲va香蕉在线| 欧美一区二区三区免费观看| 中文av一区二区| 99成人免费视频| 亚洲精品网址在线观看| 欧美激情小视频|