Visual C++ 6.0靜態、動態鏈接庫
1.什么是靜態連接庫,什么是動態鏈接庫 靜態鏈接庫與動態鏈接庫都是共享代碼的方式,如果采用靜態鏈接庫,則無論你愿不愿意,lib 中的指令都全部被直接包含在最終生成的 EXE 文件中了。但是若使用 DLL,該 DLL 不必被包含在最終 EXE 文件中,EXE 文件執行時可以“動態”地引用和卸載這個與 EXE 獨立的 DLL 文件。靜態鏈接庫和動態鏈接庫的另外一個區別在于靜態鏈接庫中不能再包含其他的動態鏈接庫或者靜態庫,而在動態鏈接庫中還可以再包含其他的動態或靜態鏈接庫。靜態鏈接庫與靜態鏈接庫調用規則總體比較如下。
對于靜態鏈接庫(比較簡單): 首先,靜態鏈接庫的使用需要庫的開發者提供生成庫的.h頭文件和.lib文件。
生成庫的.h頭文件中的聲明格式如下: extern "C" 函數返回類型 函數名(參數表); 在調用程序的.cpp源代碼文件中如下:
#include "..\lib.h"
#pragma comment(lib,"..\\debug\\libTest.lib") //指定與靜態庫一起鏈接
第二,因為靜態鏈接庫是將全部指令都包含入調用程序生成的EXE文件中。因此如果用的是靜態鏈接庫,那么也就不存在“導出某個函數提供給用戶使用”的情況,要想用就得全要!要不就都別要!:)
對于動態鏈接庫: 動態鏈接庫的使用,根據不同的調用方法,需要提供不同的資源:
1. 靜態加載------程序靜態編譯的時候就靜態導入dll,這樣的話就需要提供給庫使用者(C客戶)如下文件:*.lib文件和.dll文件和*.h。其有2個壞處:
1 程序一開始運行就需要載入整個dll,無法載入程序就不能開始運行; 2 由于載入的是整個dll,需要耗費資源較多
其調用方法如下:
#include "..\lib.h"
#pragma comment(lib,"..\\debug\\libTest.lib")
但是這種方式的話可以調用Class method.
2.動態加載-----那么只需要提供dll文件。
因此調用程序若想調用DLL中的某個函數就要以某種形式或方式指明它到底想調用哪一個函數。但是無法調用Class method了。 如果要調用Dll中的function,需要經歷3個步驟: Handle h=LoadLibrary(dllName) --> GetProcAddress(h,functionName) 返回函數指針,通過函指針調用其function-->FreeLibrary(h) 例如:Another.dll有一個int Add(int x,int y)函數。則完整的調用過程如下: typedef int (* FunPtr)(int,int);//定義函數指針
FunPtr funPtr; Handle h=LoadLibrary("Another.dll");
funPtr=(FunPtr)GetProcAddress(h,"Add");
funPtr(2,3);//2+3; FreeLibrary(h);
2.示例 示例之一: 靜態鏈接庫的創建過程: 例如:我們創建一個自定義字符串的類CHironString, 只需要在IDE里面添加class即可,然后program相應函數體 代碼如下所示: 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。 客戶調用:將CHironString.h和SDLL.lib發布給client,那么客戶端就可以調用我們編寫的靜態鏈接庫了。
示例之二: 動態鏈接庫的創建
首先我們必須先注意到DLL內的函數分為兩種: (1)DLL 導出函數,可供應用程序調用; (2)DLL 內部函數,只能在 DLL 程序使用,應用程序無法調用它們。
我們還是創建一個自定義的字符串處理類CHironString,不同之處其是一個動態鏈接庫Dll。 動態鏈接庫的export 需要在在相應的頭文件中編寫相應的MACRO MyDll.h:自定義了一些類(函數)export 宏(該文件由IDE自動生成)如下
------------------------------------------------------------------
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
這是導出類的宏定義,將導出類必須加上該宏,才能被導出。
此處的MYDLL_EXPORTS會出現在 project-->settings-->C/C++頁面上的 PreProcessor definition中,這個MACRO表明其要定義一個導出宏
CHironString.h 自定義類頭文件 ---------------------------------------------------------------- // 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; }
經過compile之后,會生成MyDll.dll和MyDll.lib文件。
客戶端的調用: 1.如果是靜態加載,那么需要提供*.lib和*.h,運行時候需提供*.dll
2.如果是動態加載,只需要提供*.dll即可。
RFID管理系統集成商 RFID中間件 條碼系統中間層 物聯網軟件集成