找回密碼
 立即注冊(cè)

QQ登錄

只需一步,快速開(kāi)始

搜索
查看: 2601|回復(fù): 0
打印 上一主題 下一主題
收起左側(cè)

靜態(tài)鏈接庫(kù)LIB和動(dòng)態(tài)鏈接庫(kù)DLL的區(qū)別 創(chuàng)建和示例

[復(fù)制鏈接]
跳轉(zhuǎn)到指定樓層
樓主
ID:107189 發(fā)表于 2016-3-5 19:56 | 只看該作者 回帖獎(jiǎng)勵(lì) |倒序?yàn)g覽 |閱讀模式
1.什么是靜態(tài)連接庫(kù),什么是動(dòng)態(tài)鏈接庫(kù)
         靜態(tài)鏈接庫(kù)與動(dòng)態(tài)鏈接庫(kù)都是共享代碼的方式,如果采用靜態(tài)鏈接庫(kù),則無(wú)論你愿不愿意,lib 中的指令都全部被直接包含在最終生成的 EXE 文件中了。但是若使用 DLL,該 DLL 不必被包含在最終 EXE 文件中,EXE 文件執(zhí)行時(shí)可以“動(dòng)態(tài)”地引用和卸載這個(gè)與 EXE 獨(dú)立的 DLL 文件。靜態(tài)鏈接庫(kù)和動(dòng)態(tài)鏈接庫(kù)的另外一個(gè)區(qū)別在于靜態(tài)鏈接庫(kù)中不能再包含其他的動(dòng)態(tài)鏈接庫(kù)或者靜態(tài)庫(kù),而在動(dòng)態(tài)鏈接庫(kù)中還可以再包含其他的動(dòng)態(tài)或靜態(tài)鏈接 庫(kù)。靜態(tài)鏈接庫(kù)與靜態(tài)鏈接庫(kù)調(diào)用規(guī)則總體比較如下。
對(duì)于靜態(tài)鏈接庫(kù)(比較簡(jiǎn)單):
首先,靜態(tài)鏈接庫(kù)的使用需要庫(kù)的開(kāi)發(fā)者提供生成庫(kù)的.h頭文件和.lib文件。

生成庫(kù)的.h頭文件中的聲明格式如下:
extern "C" 函數(shù)返回類(lèi)型 函數(shù)名(參數(shù)表);
在調(diào)用程序的.cpp源代碼文件中如下:
#include "..\lib.h"
#pragma comment(lib,"..\\debug\\libTest.lib")
//指定與靜態(tài)庫(kù)一起鏈接

第二,因?yàn)殪o態(tài)鏈接庫(kù)是將全部指令都包含入調(diào)用程序生成的EXE文件中。因此如果用的是靜態(tài)鏈接庫(kù),那么也就不存在“導(dǎo)出某個(gè)函數(shù)提供給用戶(hù)使用”的情況,要想用就得全要!要不就都別要!:)


對(duì)于動(dòng)態(tài)鏈接庫(kù):
動(dòng)態(tài)鏈接庫(kù)的使用,根據(jù)不同的調(diào)用方法,需要提供不同的資源:

1. 靜態(tài)加載------程序靜態(tài)編譯的時(shí)候就靜態(tài)導(dǎo)入dll,這樣的話(huà)就需要提供給庫(kù)使用者(C客戶(hù))如下文件:*.lib文件和.dll文件和*.h。其有2個(gè)壞處:
    1   程序一開(kāi)始運(yùn)行就需要載入整個(gè)dll,無(wú)法載入程序就不能開(kāi)始運(yùn)行;
    2   由于載入的是整個(gè)dll,需要耗費(fèi)資源較多

其調(diào)用方法如下:
#include "..\lib.h"
#pragma comment(lib,"..\\debug\\libTest.lib")

            但是這種方式的話(huà)可以調(diào)用Class method.
2.動(dòng)態(tài)加載-----那么只需要提供dll文件。
因此調(diào)用程序若想調(diào)用DLL中的某個(gè)函數(shù)就要以某種形式或方式指明它到底想調(diào)用哪一個(gè)函數(shù)。但是無(wú)法調(diào)用Class method了。
如果要調(diào)用Dll中的function,需要經(jīng)歷3個(gè)步驟:
Handle h=LoadLibrary(dllName) --> GetProcAddress(h,functionName) 返回函數(shù)指針,通過(guò)函指針調(diào)用其function-->FreeLibrary(h)
例如:Another.dll有一個(gè)int Add(int x,int y)函數(shù)。則完整的調(diào)用過(guò)程如下:
typedef int (* FunPtr)(int,int);//定義函數(shù)指針
FunPtr funPtr;
Handle h=LoadLibrary("Another.dll");
funPtr=(FunPtr)GetProcAddress(h,"Add");
funPtr(2,3);//2+3;
FreeLibrary(h);


2.示例
示例之一:
靜態(tài)鏈接庫(kù)的創(chuàng)建過(guò)程:

例如:我們創(chuàng)建一個(gè)自定義字符串的類(lèi)CHironString,
只需要在IDE里面添加class即可,然后program相應(yīng)函數(shù)體
代碼如下所示:
SDLL.h文件
------------------------------------------------------------------------
// HironString.h: interface for the CHironString class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_HIRONSTRING_H__B23C5E5E_0E8B_4030_B057_34A40C934C59__INCLUDED_)
#define AFX_HIRONSTRING_H__B23C5E5E_0E8B_4030_B057_34A40C934C59__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

class CHironString  
{
private:

char* m_data;
public:
char * GetData();
CHironString(CHironString &other);
int Length();

CHironString();
CHironString(char * str);
CHironString& operator=(CHironString &other);
virtual ~CHironString();
};

#endif // !defined(AFX_HIRONSTRING_H__B23C5E5E_0E8B_4030_B057_34A40C934C59__INCLUDED_)

SDLL.CPP如下:
--------------------------------------------------------------
// HironString.cpp: implementation of the CHironString class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "HironString.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CHironString::CHironString()
{
m_data=NULL;
}

CHironString::CHironString(char * str)
{
int len=strlen(str);
m_data=new char[len+1];
strcpy(m_data,str);

}
CHironString::~CHironString()
{
delete m_data;
}

int CHironString::Length()
{
return strlen(m_data);
}

CHironString::CHironString(CHironString &other)
{
int len=strlen(other.m_data)+1;
m_data=new char[len];
strcpy(m_data,other.m_data);
}

CHironString& CHironString::operator =(CHironString &other)
{
if(this==&other)
  return *this;
if(m_data!=NULL)
  delete[] m_data;
int len=strlen(other.m_data)+1;
m_data=new char[len];
strcpy(m_data,other.m_data);
return *this;
}

char * CHironString::GetData()
{
return m_data;
}

然后,將程序編譯后生成sdll.lib。
客戶(hù)調(diào)用:將CHironString.h和SDLL.lib發(fā)布給client,那么客戶(hù)端就可以調(diào)用我們編寫(xiě)的靜態(tài)鏈接庫(kù)了。

示例之二:
動(dòng)態(tài)鏈接庫(kù)的創(chuàng)建


首先我們必須先注意到DLL內(nèi)的函數(shù)分為兩種:
(1)DLL 導(dǎo)出函數(shù),可供應(yīng)用程序調(diào)用;
(2)DLL 內(nèi)部函數(shù),只能在 DLL 程序使用,應(yīng)用程序無(wú)法調(diào)用它們。

我們還是創(chuàng)建一個(gè)自定義的字符串處理類(lèi)CHironString,不同之處其是一個(gè)動(dòng)態(tài)鏈接庫(kù)Dll。
動(dòng)態(tài)鏈接庫(kù)的export 需要在在相應(yīng)的頭文件中編寫(xiě)相應(yīng)的MACRO
MyDll.h:自定義了一些類(lèi)(函數(shù))export 宏(該文件由IDE自動(dòng)生成)如下
------------------------------------------------------------------
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif

這是導(dǎo)出類(lèi)的宏定義,將導(dǎo)出類(lèi)必須加上該宏,才能被導(dǎo)出。
此處的MYDLL_EXPORTS會(huì)出現(xiàn)在 project-->settings-->C/C++頁(yè)面上的 PreProcessor definition中,這個(gè)MACRO表明其要定義一個(gè)導(dǎo)出宏
CHironString.h 自定義類(lèi)頭文件
----------------------------------------------------------------
// HironString.h: interface for the CHironString class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_HIRONSTRING_H__518E9EC4_0837_4E45_9516_7D6A70CD3D0F__INCLUDED_)
#define AFX_HIRONSTRING_H__518E9EC4_0837_4E45_9516_7D6A70CD3D0F__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#include "MyDll.h"

class MYDLL_API CHironString   //加上MYDLL_API表明此為Export Class
{
private:

char* m_data;
public:
char * GetData();
CHironString(CHironString &other);
int Length();

CHironString();
CHironString(char * str);
CHironString& operator=(CHironString &other);
virtual ~CHironString();

};
#endif // !defined(AFX_HIRONSTRING_H__518E9EC4_0837_4E45_9516_7D6A70CD3D0F__INCLUDED_)


CHironString.Cpp
------------------------------------------------------------

// HironString.cpp: implementation of the CHironString class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "HironString.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CHironString::CHironString()
{
m_data=NULL;
}
CHironString::CHironString(char * str)
{
int len=strlen(str);
m_data=new char[len+1];
strcpy(m_data,str);
}
CHironString::~CHironString()
{
delete m_data;
}
int CHironString::Length()
{
return strlen(m_data);
}
CHironString::CHironString(CHironString &other)
{
int len=strlen(other.m_data)+1;
m_data=new char[len];
strcpy(m_data,other.m_data);
}
CHironString& CHironString::operator =(CHironString &other)
{
if(this==&other)
  return *this;
if(m_data!=NULL)
  delete[] m_data;
int len=strlen(other.m_data)+1;
m_data=new char[len];
strcpy(m_data,other.m_data);
return *this;
}
char * CHironString::GetData()
{
return m_data;
}
經(jīng)過(guò)compile之后,會(huì)生成MyDll.dll和MyDll.lib文件。

客戶(hù)端的調(diào)用:
1.如果是靜態(tài)加載,那么需要提供*.lib和*.h,運(yùn)行時(shí)候需提供*.dll

2.如果是動(dòng)態(tài)加載,只需要提供*.dll即可。


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏 分享淘帖 頂 踩
回復(fù)

使用道具 舉報(bào)

本版積分規(guī)則

小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術(shù)交流QQ群281945664

Powered by 單片機(jī)教程網(wǎng)

快速回復(fù) 返回頂部 返回列表