C/C++::淺談.obj .exe .dll .lib關係&& .o .a .so關係

淺談.lib .dll .obj 關係&& .a .so .o關係 


一、.obj .exe .dll .lib

(1).obj

  • 目標文件,相當於源代碼對應的二進制文件。
  • obj文件就是用.c .cpp .h文件經過編譯器編譯之後生成的目標文件。

(2).exe

  • 將程序運行所需要的全部.obj文件連接起來,即形成.exe文件。
  • 也就是windows下的可執行文件。
  • obj只給出了程序的相對地址,而EXE是絕對地址

(3).dll

  •  .dll是可提供給多個程序同時使用的可執行代碼和數據(資源 )的庫
  • 可簡單理解爲封裝好的.cpp,裏面裝的是函數的具體實現
  • .dll是動態編譯出來的程序運行時所需要的庫,沒有.dll文件,動態編譯的程序就不能運行

(4).lib

  • .lib是編譯程序時所需的,非運行時所需
  • .lib分爲靜態和動態
  • 靜態.lib包括了方法及其具體實現。
  • 動態.lib只有方法的聲明,簡單來看相當於一個h文件,是對實現部分(.dll文件)的導出部分的聲明。作用是告訴鏈接器具體用到了哪個dll文件,以及定位到dll文件內部的函數具體實現位置。
  • 利用靜態lib編譯出來的程序,運行時不需要.dll文件的支持。
  • 利用動態lib編譯出來的程序,運行時需要.dll文件提供方法的具體實現
  • 實際上:.lib文件可看做是若干個.obj文件的集合

(5)一個C/C++工程需要用到其他.c .h .cpp類庫、函數庫時,其包含的方式有如下圖的幾種方式

  • 1、最直接的方式就是將該類庫的.h .cpp 直接引入到工程中,直接完全編譯
  • 2、另外的方法是先將該類庫生成爲一個靜態的lib庫,引入工程時只需包含.h以及.lib文件,編譯時將所需的方法具體實現從.lib中提取到可執行文件,可執行文件可不需要其他東西的支持就可直接運行
  • 3、常用的方法是將該類庫生成一個動態的lib庫,還有與之對應的.dll文件,引入工程時也只需包含.h以及.lib文件,但這個動態的.lib文件僅僅提供方法的聲明,具體的實現被打包在.dll文件中,因此運行生成的可執行文件需要.dll文件的支持

實戰:

1)動態庫的生成(lib和dll)

a、新建項目,win32,win32項目,輸入項目名稱,例如makedll2

b、選擇dll、導出符號

c、自動生成makedll2.h

  • #define MAKEDLL2_API __declspec(dllexport)表明這些東西可以被外部函數使用,即(dllexport)是把DLL中的相關代碼(類,函數,數據)暴露出來爲其他應用程 序使用
  • class MAKEDLL2_API Cmakedll2  表示導出類,這個類爲Cmakedll2類
  • extern MAKEDLL2_API int nmakedll2;  聲明導出變量
  • MAKEDLL2_API int fnmakedll2(void);  聲明導出函數
// 下列 ifdef 塊是創建使從 DLL 導出更簡單的
// 宏的標準方法。此 DLL 中的所有文件都是用命令行上定義的 MAKEDLL2_EXPORTS
// 符號編譯的。在使用此 DLL 的
// 任何其他項目上不應定義此符號。這樣,源文件中包含此文件的任何其他項目都會將
// MAKEDLL2_API 函數視爲是從 DLL 導入的,而此 DLL 則將用此宏定義的
// 符號視爲是被導出的。
#ifdef MAKEDLL2_EXPORTS
#define MAKEDLL2_API __declspec(dllexport)
#else
#define MAKEDLL2_API __declspec(dllimport)
#endif

// 此類是從 makedll2.dll 導出的   類名爲Cmakedll2
class MAKEDLL2_API Cmakedll2 {
public:
	Cmakedll2(void);
	// TODO:  在此添加您的方法。
};

//聲明導出變量
extern MAKEDLL2_API int nmakedll2;

//聲明導出函數
MAKEDLL2_API int fnmakedll2(void);

d、makedll2.cpp

  • 導出內容的具體實現
// makedll2.cpp : 定義 DLL 應用程序的導出函數。
//

#include "stdafx.h"
#include "makedll2.h"


// 這是導出變量的一個示例
MAKEDLL2_API int nmakedll2=0;

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

// 這是已導出類的構造函數。
// 有關類定義的信息,請參閱 makedll2.h
Cmakedll2::Cmakedll2()
{
	return;
}

 e、構建

f、檢查生成的.dll和.lib

 2)動態庫的使用

方式一、vs2013下進行項目配置

a、新建一個win32控制檯項目

b、在屬性管理器中,雙擊debug或者release

將包含目錄設置爲剛剛生成dll項目的頭文件.h所在文件夾

將庫目錄設置爲剛剛生成dll項目的debug文件夾,也就是.lib所在的文件夾

c、在鏈接器--->輸入頁面中,在附加依賴項中添加剛剛生成的.lib文件

c、新建main.cpp文件,對剛剛封裝的庫進行調用

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

int main()
{
	Cmakedll2 testdll; //這個是剛剛封裝成lib裏面的導出類
	//輸出導出變量
	cout <<"這個是導出變量:"<< nmakedll2 << endl;
	//調用的導出函數
	cout << "調用導出函數輸出:" << fnmakedll2() << endl;
	system("pause");
	return 0;
}

 d、點擊運行,應該會報錯如下:

e、將上面生成的庫.dll文件複製到這個項目的debug下

f、運行,得到如下結果:

 方式二、直接在項目中添加lib文件【適用於lib文件較少的情況】

a)新建完項目後,項目視圖中右鍵,添加,現有項,選擇所生成的lib文件即可

b)庫的.h頭文件放在項目目錄下

c)庫的.dll文件放在項目的debug目錄下

方式三、 直接在源文件中加入代碼

#pragma comment(lib, "makedll2.lib")

這裏引用https://www.cnblogs.com/qinguoyi/p/7257353.html的總結,

動態庫使用方法總結

  .h,.lib,.dll的添加方法其實各有很多種。

.h有兩種:

  1. 頭文件較少時,直接放在工程目錄下,#include "*.h"

  2. 建立include文件夾,放在裏面,然後在項目屬性的“VC++目錄”-》“包含目錄”,添加.h路徑即可。

.lib的方法有兩種

  1.lib文件較少時,直接放在工程目錄下,#pragma comment(lib, "testCpp.lib")

  2.建立lib文件夾,目屬“VC++目錄”-》“庫目錄”添加路徑,然後在項目屬性的“鏈接器”-》“輸入”-》“附加依賴項”,添加.lib名字。

dll的方法有兩種

  1.直接放在debug/release目錄下

  2.建立bin文件夾,放在裏面,然後在項目“環境”中添加bin的路徑(PS:最好不要用這個)

 3)靜態庫的生成和使用可參考動態庫,使用時不再需要將.dll文件複製到exe目錄,因爲靜態編譯將exe所需的內容都提取到exe裏面了。

 



 二、.a .so .o

(1).o

  • 目標文件,相當於windows下的.obj
  • 是編譯得到的結果,即源碼編譯後得到的二進制文件

(2).a 

  • 靜態庫文件
  • 相當於windows下的靜態.lib
  • 相當於一個或多個.o文件的集合,可直接由.o文件生成
  • .a的命名格式:lib+函數庫名+.a
  • 構建.a靜態庫方法:使用ar工具
  • 使用.a靜態庫方法:gcc生成可執行文件時,使用-l(小寫)參數指定要加入的庫函數。也可以用ld命令的-l和-L參數
  • 使用舉例:gcc -o hello main.c -L. –l庫名     #-L 後面指定靜態庫路徑   -l不用空格後直接加靜態庫名(lib後面的東西)

(3).so

  • 動態庫文件,一般叫共享庫,share
  • 相當於windows下的.dll
  • .so的命名格式:lib+函數庫名+.so+版本號信息(但是記住,非常底層的C庫函數都不是以lib開頭命名的)
  • 構建.so動態庫方法:gcc -fPIC -shared -o lib庫名.so.1 atoi.c
  • 使用.so動態庫方法:gcc -o main main.o -Wl,-rpath=. lib庫名.so.1     #-Wl,-rpath:指定庫所在路徑
  • 查看可執行文件所依賴的動態庫情況:ldd  可執行文件

 

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