<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          c語言邊角料5:一個跨平臺的頭文件

          共 2857字,需瀏覽 6分鐘

           ·

          2021-04-01 14:56


          • 一、前言

          • 二、頭文件

          • 三、預(yù)定義的宏

          • 四、Windows 平臺場景分析

          • 五、Linux 平臺場景分析


          一、前言

          我們平常在寫代碼的時候,特別是在制造輪子的時候(為別人提供庫文件),會遇到各種不同的需求場景:

          1. 有些人需要在 Linux 系統(tǒng)下使用,有些人需要在 Windows 系統(tǒng)下使用;
          2. 有些人使用 C 語言開發(fā),有些人使用 C++ 來開發(fā);
          3. 有些人使用動態(tài)庫,有些人使用靜態(tài)庫;

          特別是在 Windows 系統(tǒng)中,庫文件中導(dǎo)出的函數(shù)需要使用 _declspec(dllexport) 來聲明函數(shù),而使用者在導(dǎo)入的時候,需要使用 _declspec(dllimport) 來聲明函數(shù),甚是麻煩!

          這篇短文分享一個頭文件,利用這個頭文件,再加上幾個編譯期間傳遞的宏,就可以完美的處理剛才所說的各種需求。

          二、頭文件

          先直接上代碼,可以先試著分析一下,后面我們再逐一分析不同的使用場景。

          這個頭文件的主要目的,就是定義一個宏:MY_API,然后把這個宏添加在庫文件中每一個需要導(dǎo)出的函數(shù)或者的聲明中即可。例如:

          void MY_API do_work();

          下面是頭文件:

          _Pragma("once")

          #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__)
          #define MY_WIN32
          #elif defined(linux) || defined(__linux) || defined(__linux__)
          #define MY_LINUX
          #endif

          #if defined(MY_WIN32)
          #ifdef MY_API_STATIC
          #ifdef __cplusplus
          #define MY_API extern "C"
          #else
          #define MY_API
          #endif
          #else
          #ifdef MY_API_EXPORTS
          #ifdef __cplusplus
          #define MY_API extern "C" __declspec(dllexport)
          #else
          #define MY_API __declspec(dllexport)
          #endif
          #else
          #ifdef __cplusplus
          #define MY_API extern "C" __declspec(dllimport)
          #else
          #define MY_API __declspec(dllimport)
          #endif
          #endif
          #endif
          #elif defined(MY_LINUX)
          #ifdef __cplusplus
          #define MY_API extern "C"
          #else
          #define MY_API
          #endif
          #endif

          三、預(yù)定義的宏

          假設(shè)需要寫一個庫文件,提供給別人使用。定義了上面這個頭文件之后,其他的文件中都要 include 這個頭文件。

          1. 平臺宏定義

          不同的平臺預(yù)定義了相應(yīng)的宏定義,例如:

          Windows 平臺:WIN32, _WIN32, WIN32;
          Linux 平臺:linux, __linux, linux;

          在一個確定的平臺上,這些宏不一定全部定義,很可能只有其中的某一個宏是被定義的。

          為了統(tǒng)一性,我們在頭文件的剛開始部分,把這些可能的宏統(tǒng)一起來,定義我們出我們自己的平臺宏定義:MY_WIN32 或者是 MY_LINUX,后面需要區(qū)分不同的平臺時,就用這個自己定義的平臺宏。

          當然,還可以繼續(xù)擴充出其他平臺,例如:MY_MAC, MY_ARM 等等。

          2. 編譯器宏定義

          如果在寫庫代碼的時候,使用的是 C++,而使用者使用的是 C 語言,那么就需要對庫函數(shù)進行 extern “C” 聲明,讓編譯器不要對函數(shù)的名稱進行改寫。

          編譯器 g++ 預(yù)定義了宏 __cplusplus,因此,在頭文件中,就利用了這個宏,在 MY_API 中添加 extern "C" 聲明。

          四、Windows 平臺場景分析

          1. 編譯生成庫文件

          (1) 生成靜態(tài)庫

          在靜態(tài)庫中,不需要 __declspec(dllexport/dllimport) 的聲明,因此只需要區(qū)分編譯器即可(gcc or g++),在編譯選項中定義宏 MY_API_STATIC,即可得到最終的 MY_API 為:

          gcc 編譯器:#define MY_API  
          g++ 編譯器:#define MY_API extern "C"  

          (2) 生成動態(tài)庫

          在編譯選項中,定義宏 MY_API_EXPORTS,這樣最終得到的 MY_API 就會變成:

          gcc 編譯器:#define MY_API __declspec(dllexport) 

          g++ 編譯器:#define MY_API extern "C" __declspec(dllexport)

          2. 使用庫

          使用庫的應(yīng)用程序中,也需要在代碼中 include 這個頭文件,然后加上編譯選項中定義的各種宏,來生成對應(yīng)的 MY_API 宏定義。

          (1) 使用靜態(tài)庫

          需要在編譯選項中定義 MY_API_STATIC,即可得到最終的 MY_API 為:

          gcc 編譯器:#define MY_API
          g++ 編譯器:#define MY_API extern "C"

          (2) 使用動態(tài)庫

          在編譯選項中不需要任何宏定義,即可得到最終的 MY_API 為:

          gcc 編譯器:#define MY_API extern "C" __declspec(dllimport) 

          g++ 編譯器:#define MY_API __declspec(dllimport)

          這樣就相當于聲明導(dǎo)入庫函數(shù)了。

          五、Linux 平臺場景分析

          Linux 平臺下就簡單多了,只需要注意編譯器的問題,而沒有導(dǎo)出和導(dǎo)入之分。


          好文章,要轉(zhuǎn)發(fā);越分享,越幸運!

          星標公眾號,能更快找到我!




          推薦閱讀

          1. C語言指針-從底層原理到花式技巧,用圖文和代碼幫你講解透徹
          2. 原來gdb的底層調(diào)試原理這么簡單
          3. 一步步分析-如何用C實現(xiàn)面向?qū)ο缶幊?/a>
          4. 都說軟件架構(gòu)要分層、分模塊,具體應(yīng)該怎么做(一)
          5. 都說軟件架構(gòu)要分層、分模塊,具體應(yīng)該怎么做(二)


          瀏覽 68
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  影音先锋午夜性爱av | 青娱乐亚洲天堂 | 午色婷婷国产无码 | 激情五月天色青五月天 | 青青草视频首页 |