C++生成和使用庫文件

庫文件分爲靜態庫和動態庫。

一、介紹

1.靜態庫

一種是LIB包含函數代碼本身,在編譯時直接將代碼加入程序當中,稱爲靜態鏈接庫(lib庫)。

靜態鏈接使用靜態鏈接庫,鏈接器從靜態鏈接庫LIB獲取所有被引用函數,並將庫同代碼一起放到可執行文件中。

2.動態庫

一種是LIB包含了函數所在的DLL文件和文件中函數位置的信息(入口),代碼由運行時加載在進程空間中的DLL提供,稱爲動態鏈接庫(dll庫)。

動態鏈接使用動態鏈接庫,允許可執行模塊(.dll文件或.exe文件)僅包含在運行時定位DLL函數的可執行代碼所需的信息。


二、區別

         (1)lib是編譯時用到的,dll是運行時用到的。如果要完成源代碼的編譯,只需要lib;如果要使動態鏈接的程序運行起來,只需要dll。

  (2)如果有dll文件,那麼lib一般是一些索引信息,記錄了dll中函數的入口和位置,dll中是函數的具體內容;如果只有lib文件,那麼這個lib文件是靜態編譯出來的,索引和實現都在其中。使用靜態編譯的lib文件,在運行程序時不需要再掛動態庫,缺點是導致應用程序比較大,而且失去了動態庫的靈活性,發佈新版本時要發佈新的應用程序纔行。

  (3)動態鏈接的情況下,有兩個文件:一個是LIB文件,一個是DLL文件。LIB包含被DLL導出的函數名稱和位置,DLL包含實際的函數和數據,應用程序使用LIB文件鏈接到DLL文件。在應用程序的可執行文件中,存放的不是被調用的函數代碼,而是DLL中相應函數代碼的地址,從而節省了內存資源。DLL和LIB文件必須隨應用程序一起發行,否則應用程序會產生錯誤。如果不想用lib文件或者沒有lib文件,可以用WIN32API函數LoadLibrary、GetProcAddress裝載。

  使用lib需注意兩個文件:

  (1).h頭文件,包含lib中說明輸出的類或符號原型或數據結構。應用程序調用lib時,需要將該文件包含入應用程序的源文件中。

  (2).LIB文件,略。

  使用dll需注意三個文件:

  (1).h頭文件,包含dll中說明輸出的類或符號原型或數據結構的.h文件。應用程序調用dll時,需要將該文件包含入應用程序的源文件中。

  (2).LIB文件,是dll在編譯、鏈接成功之後生成的文件,作用是當其他應用程序調用dll時,需要將該文件引入應用程序,否則產生錯誤。如果不想用lib文件或者沒有lib文件,可以用WIN32API函數LoadLibrary、GetProcAddress裝載。

  (3).dll文件,真正的可執行文件,開發成功後的應用程序在發佈時,只需要有.exe文件和.dll文件,並不需要.lib文件和.h頭文件。


三、生成和使用

1.lib庫的生成和使用

1.1 生成

建立一個控制檯工程,在選擇應用程序類型裏面,勾選lib,然後添加cpp文件和頭文件。

cpp文件libGen.cpp

#include "libGen.h"
#include <iostream>
using namespace std;

int myadd(int x, int y)
{
	int sum;
	sum = x + y;
	return sum;
}

頭文件libGen.h

#ifndef _MYADD_H
#define _MYADD_H
int myadd(int x, int y);
#endif

然後點擊“生成”,就可以得到庫文件libGen.lib


1.2 使用

別的工程要使用這個lib有兩種方式:

  (1)在project->link->Object/LibraryModule中加入libGen.lib文件(先查詢工程目錄,再查詢系統Lib目錄);或者在源代碼中加入指令#pragmacomment(lib,“libGen.lib”)。

  (2)將libGen.lib拷入工程所在目錄,或者執行文件生成的目錄,或者系統Lib目錄中。

  (3)加入相應的頭文件libGen.h。

建立一個控制檯程序,將頭文件和lib庫文件拷貝到工程目錄下,然後在頭文件夾裏面導入頭文件libGen.h,最後再寫cpp文件,代碼如下:

#include "libGen.h"
#include <iostream>
using namespace std;
#pragma comment(lib,"libGen.lib") //加入鏈接庫

void main()
{
	int sum;
	sum = myadd(1, 2);
	cout << sum << endl;
	system("pause");
}


2.dll庫的生成和使用

2.1 生成

建立一個控制檯工程,在選擇應用程序類型裏面,勾選dll,然後添加cpp文件和頭文件。

cpp文件dllGen.cpp

#include "dllGen.h"
#include <iostream>
using namespace std;

int myadd(int x, int y)
{
	int sum;
	sum = x + y;
	return sum;
}

頭文件dllGen.h

#ifndef _MYADD_H
#define _MYADD_H
__declspec(dllexport) int myadd(int x, int y);
#endif

注:導出函數的聲明方式有兩種,一種在函數聲明類型和函數名之間加上“_declspec(dllexport)”,另一種採用模塊定義(.def)文件聲明,需要在庫工程中添加模塊文件,格式如下:

LIBRARY 庫工程名稱 

EXPORTS 導出函數名


2.2 使用

方式1:隱式鏈接

建立一個控制檯程序,將頭文件dllGen.h,生成的lib和dll文件拷貝到工程目錄下,然後在頭文件夾裏面導入頭文件dllGen.h,最後再寫cpp文件,代碼如下:

#include "dllGen.h"
#include <iostream>
using namespace std;
#pragma comment(lib,"dllGenTest.lib") //加入鏈接庫

void main()
{
	int sum;
	sum = myadd(10, 2);
	cout << sum << endl;
	system("pause");
}


方式2:顯式鏈接

#include <iostream>
using namespace std;
#include <windows.h>

typedef int(*lpAddFun)(int, int);//定義一個與myadd函數接受參數類型和返回//值均相同的函數指針類型

int main()
{
	HINSTANCE hDll;//句柄

	lpAddFun addFun;//函數指針

	hDll = LoadLibrary("dllGenTest.dll");//動態加載DLL模塊句柄

	if (hDll == NULL)
	{
		FreeLibrary(hDll);
	}

	//addFun = (lpAddFun)GetProcAddress(hDll, "myadd"); //通過函數名獲取函數的地址,不work,why?
	addFun = (lpAddFun)GetProcAddress(hDll, MAKEINTRESOURCE(1)); //通過函數的序號獲取函數的地址,work
	
	if (addFun == NULL)
	{
		FreeLibrary(hDll);
	}

	int result;
	result = addFun(22,33);
	cout << result << endl;
	system("pause");

	FreeLibrary(hDll);

	return 0;
}

後記,在開發過程中,用到包含多個庫的庫調用,也是可以實現的。

 

參考:

http://blog.csdn.net/lxwzsh/article/details/20451087

http://blog.csdn.net/crich_moon/article/details/6039939http://haofu.blog.51cto.com/287980/55851

http://www.cnblogs.com/coder2012/archive/2013/04/27/3046573.html

http://m.blog.csdn.net/blog/oyanghaizhi/38379651

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章