1. 程式人生 > >linux下建立,使用動態庫

linux下建立,使用動態庫

1. 現在要生成libmydll.so的庫檔案,標頭檔案如下

#ifndef  _MYDLL_H
#define  _MYDLL_H
#include "stdio.h"

#ifdef WIN32
    #ifdef MYDLL_EXPORTS
        #define MYDLLAPI  extern "C" __declspec(dllexport)
    #else
        #define MYDLLAPI  extern "C" __declspec(dllimport)
    #endif
#else
    #define MYDLLAPI extern "C"
#endif


#define MAXBUFLEN  0x1000000

MYDLLAPI  int Add(int x, int y);
MYDLLAPI  int TestWrite(char *p, int buflen = MAXBUFLEN);

#endif

命令:  g++ mydll.cpp -fPIC -shared -o libmydll.so

-shared表示生成共享庫, -fPIC表示生成的庫可以重入

2. 如果依賴標頭檔案, 則使用 -I +路徑包括

 g++  -o ../yu.a  yu.cpp -I../../     //在上一級的目錄上生成yu.a

3.這裡如果動態庫與cpp不在同一個目錄下,就是用-L + 動態庫的路徑。

g++ main.cpp -I../../mydll -L../../mydll -lmydll -o main.a

或者 g++ main.cpp -I../../mydll  ../../mydll/libmydll.so  -o main.a也可以,但是名稱必須是 libmydll.so這樣有字首的,否則錯誤

當依賴多個動態庫的時候,依次加上動態庫就可以了

 g++ main.cpp -I../../mydll -I../../JTFS -L../../mydll -lmydll -L../../JTFS -ljtfs -o main.a或者寫成

 g++ main.cpp -I../../mydll -I../../JTFS -L../../mydll -L../../JTFS -ljtfs -lmydll  -o main.a

注意,這裡還要將庫加到環境變數中,否則執行的時候提示找不到庫

4.新增動態庫搜尋路徑   

   (1)export  LD_LIBRARY_PATH=$LD_LIBRAR_PATH:/路徑     注意等於號左右2邊不要加空格,不然提示找不到路徑

        export功能是建立一個新的環境變數

        檢視當前的所有環境變數 env

   (2) 開啟/etc/ld.so.conf檔案, 直接新增你的路徑,儲存好ldconfig即可.例如:     

         include ld.so.conf.d/*.conf

         /home/ywy/liuzaoxiang/80/videoDownloadSDK/version

5.檢視動態庫的內容

靜態庫用ar -t YourFile

動態庫用 nm -D YourFile

6.動態庫靜態載入時,在程式執行時被載入進記憶體,程式退出時才退出記憶體,多個執行緒呼叫時全域性變數變數和靜態變數公用一塊區域, 需要加鎖。

動態載入時LoadLibrary載入動態庫到記憶體,FreeLibrary清理記憶體。

7.在linxu下新增新的動態庫後,如果無法使用。則執行ldconfig

8. windows下庫函式重複定義: /FORCE:MULTIPLE

9.   windows靜態庫可以直接匯出類, 動態庫匯出類需要新增關鍵字__declspec(dllexport).

      linux動態庫和靜態庫可直接匯出類

 #ifdef WIN32
#ifdef MYDLL_EXPORTS
#define MYDLLCLASS   __declspec(dllexport)
#else
#define MYDLLCLASS   __declspec(dllimport)
#endif
#else
#define MYDLLCLASS
#endif

class MYDLLCLASS CTest
{
public:
 CTest();
 ~CTest();
public:
 int Add(int , int);
 int m_iSum;
 virtual void Help();
};

10.動態庫後面的數字含義

     如libiconv.so.2等,數字一般表示版本號,在使用的時候可以為libiconv.so.2建立一個硬連結libiconv.so,宿主模組直接通過LD_LIBRARY_PATH或其他方法連結到libiconv.so就可以呼叫libiconv.so.2的庫了.如果升級,如有libiconv.so.3,只需要修改連結就可以了。

     關於連結

如果一個檔案有連結如libmydll.so則:

ll -i  *.txt

1070305 -rw-r--r-- 3 root root 0 Jan 15 11:09 my.txt   //硬連結 有3個連結
1070305 -rw-r--r-- 3 root root 0 Jan 15 11:09 she.txt
1070304 lrwxrwxrwx 1 root root 6 Jan 15 11:10 you.txt -> my.txt //軟連結

通過find / -inum 1070305可以找到所有的連結檔案

可以為動態庫建立一個硬連結到/usr/lib或者/lib,這樣宿主就能直接使用。軟連結不可直接使用

11. 動態庫中的全域性變數問題 (這個是轉載的)

       在Win16環境中,DLL的全域性資料對每個載入它的程序來說都是相同的,因為所有的程序用的都收同一塊地址空間;而在Win32環境中,情況卻發生了變化,每個程序都有了它自己的地址空間,DLL函式中的程式碼所建立的任何物件(包括變數)都歸呼叫它的程序所有。當程序在載入DLL時,作業系統自動把DLL地址對映到該程序的私有空間,也就是程序的虛擬地址空間,而且也複製該DLL的全域性資料的一份拷貝到該程序空間。(在實體記憶體中,多程序載入DLL時,DLL的程式碼段實際上是隻載入了一次,只是將實體地址對映到了各個呼叫它的程序的虛擬地址空間中,而全域性資料會在每個程序都分別載入)。也就是說每個程序所擁有的相同的DLL的全域性資料,它們的名稱相同,但其值卻並不一定是相同的,而且是互不干涉的。

在DLL的實現檔案中新增下列程式碼:

#pragma data_seg("DLLSharedSection")      // 宣告共享資料段,並命名該資料段
int SharedData = 50;       // 必須在定義的同時進行初始化!!!!
#pragma data_seg()

 在#pragma data_seg("DLLSharedSection")和#pragma data_seg()之間的所有變數將被訪問該Dll的所有程序看到和共享。僅定義一個數據段還不能達到共享資料的目的,還要告訴編譯器該段的屬性,有三種方法可以實現該目的(其效果是相同的),一種方法是在.DEF檔案中加入如下語句:

SETCTIONS
    DLLSharedSection READ WRITE SHARED

另一種方法是在專案設定的連結選項(Project Setting --〉Link)中加入如下語句:

/SECTION:DLLSharedSection,rws

還有一種就是使用指令:

#pragma comment(linker,"/section:.DLLSharedSection,rws")

那麼這個資料節中的資料可以在所有DLL的例項之間共享了。所有對這些資料的操作都針對同一個例項的,而不是在每個程序的地址空間中都有一份。
 
當程序隱式或顯式呼叫一個動態庫裡的函式時,系統都要把這個動態庫對映到這個程序的虛擬地址空間裡。這使得DLL成為程序的一部分,以這個程序的身份執行,使用這個程序的堆疊。

下面來談一下在具體使用共享資料段時需要注意的一些問題:

·         所有在共享資料段中的變數,只有在資料段中經過了初始化之後,才會是程序間共享的。如果沒有初始化,那麼程序間訪問該變數則是未定義的。
·         所有的共享變數都要放置在共享資料段中。如何定義很大的陣列,那麼也會導致很大的DLL。
·         不要在共享資料段中存放程序相關的資訊。Win32中大多數的資料結構和值(比如HANDLE)只在特定的程序上下文中才是有效地。
·         每個程序都有它自己的地址空間。因此不要在共享資料段中共享指標,指標指向的地址在不同的地址空間中是不一樣的。
·         DLL在每個程序中是被對映在不同的虛擬地址空間中的,因此函式指標也是不安全的。

當然還有其它的方法來進行程序間的資料共享,比如檔案記憶體對映等,這就涉及到通用的程序間通訊了,這裡就不多講了。

12.程序呼叫dll裡開闢的記憶體,屬於呼叫程序記憶體。

13.g++安裝  http://jingyan.baidu.com/article/a3f121e4faf03bfc9052bbeb.html 

 注意: 一定要選擇支援的版本

14.檢視.so編譯的GCC版本

strings -a libxxx.so |grep -i gcc

GCC: (Ubuntu 4.8.4-2ubuntu1~14.04.3) 4.8.4



相關推薦

linux建立使用動態

1. 現在要生成libmydll.so的庫檔案,標頭檔案如下 #ifndef  _MYDLL_H #define  _MYDLL_H #include "stdio.h" #ifdef WIN32     #ifdef MYDLL_EXPORTS         #defi

Linux靜態、動態(隱式、顯式呼叫)的建立和使用及區別

顯式呼叫的動態庫的建立與隱式呼叫相同。(隱式呼叫與靜態庫的使用方法一樣,不需要包含匯出函式的標頭檔案(顯式呼叫也不用包含標頭檔案),只需要在編譯可執行程式時指定庫檔案的路徑)顯式呼叫和隱式呼叫的區別在於:編譯可執行程式時需要指定庫檔案的搜尋路徑,而顯式呼叫編譯可執行程式時不用加上動態庫的搜尋路徑(因為已經在主

Linux如何解決動態的鏈接問題

gcc 動態庫 error while loading shared libraries 關於動態庫和靜態庫,這裏不多解釋,如何創建屬於自己的動態庫和靜態庫,之前有提過,詳細內容戳鏈接。 靜態庫是一種以空間換取時間和移植性的做法,一些情況下確實有著一定的意義,但是一些情況下,我們自己

LinuxC程式動態的生成和呼叫

Linux下C程式動態庫的生成和呼叫 文章目錄 Linux下C程式動態庫的生成和呼叫 1 動態庫的打包和呼叫 2 靜態庫打包和呼叫 3 常用命令 4 gcc 和 g++ 區別 5 編譯和連結的理解

linux製作一個動態

製作一個動態庫 我們可以使用gcc工具來製作一個動態庫 示例:自己製作一個動態庫,庫函式的功能是傳遞一個字串並輸出。 第一步:需要準備3個檔案:hello.h、hello.c、test.c。其中hello.h和hello.c用於製作動態庫,test.c是測試程式主函式 第

Linux.h與動態.so檔案的路徑新增及gcc編譯的記錄

使用場景 當你在程式中加入一個非gcc預設搜尋路徑上的一個.h標頭檔案時,會報錯“No such file”,當你的程式需要動態連結一個.so庫時,在預設路徑裡找不到該庫,也會報錯。那麼,如何解決這兩種問題呢? gcc編譯使用“-I”選項 當頭檔案非標

Linux建立進入目錄的許可權建立並顯示普通檔案的許可權

許可權: 檔案許可權 1.檔案訪問者: 擁有者u——-user 所屬組g——-group 其他使用者o—–other 2.檔案訪問許可權的種類: 可讀(r) 可寫(w) 可執行(x) 建立一個目錄,並進入 目錄test

Linux建立動態

動態庫簡介 在Linux下動態庫檔案字尾為.so, 其中so代表 Shared Object,即共享目標檔案。 動態庫的特點就是在系統記憶體中,只會存在動態庫的一個副本。例如:程式A,B允許時都需要

linux生成使用靜態和動態連結

當要使用靜態的程式庫時,聯結器會找出程式所需的函式,然後將它們拷貝到執行檔案,由於這種拷貝是完整的,所以一旦連線成功,靜態程式庫也就不再需要了。 然而,對動態庫而言,就不是這樣。動態庫會在執行程式內留下一個標記‘指明當程式執行時,首先必須載入這個庫。由於動態庫節省空間,li

【C++】linuxCMake生成動態連結g++包含生成動態連結

一、前言   由於專案中要用到java呼叫C++的庫檔案,於是需要在linux下編譯連線生成動態庫,然後根據Recast官方包要先CMake生成編譯,然後在包含到自己實現的檔案,網上查了半天,坑爹沒有全面的,東拼西湊終於才明白原理,於是總結記錄分享如下。 二、CMake生

linux添加動態鏈接路徑、動態加載等方法

文件 -c 指定 時有 歸檔 最好 開始 動態 SM linux下添加動態鏈接庫路徑的方法 2017年01月20日 10:08:17 閱讀數:5596 Linux共享庫路徑配置   Linux下找不到共享庫文件的典型現象為明明已經安裝某個軟包(如libne

linux建立動態

1.gcc編譯選項 -E : 預處理 .c -> .i -S : 編譯 .i /.c -> .s -c : 彙編 .s -> .o -g : 生成除錯資訊 -O : 優化級別 -O0 -O1 -O2 -O3 -Os -I : 包含一個頭檔案搜尋路徑 -I/home/li

ubuntun16.04+cuda9.0+cudnn7+anaconda3+pytorch+anaconda3py2安裝pytorch Anaconda3+python3環境如何建立python2環境(win+Linux適用同一個anacondapy2/3共存)

一、電腦配置 說明: 電腦配置: LEGION筆記本 CPU Inter Core i7 8代 GPU NVIDIA GeForce GTX1060 Windows10 所需的環境: Anaconda3(64bit)CUDA-9.0CuDNN-7.1 二、安裝c

QtEmbedded-4.8.6-arm 編譯選擇從 動態變化到靜態生成的Makefile連結路徑如果有動態和靜態優先選擇動態編譯應用

問題:QtEmbedded-4.8.6-arm 編譯選擇從 動態庫到靜態庫 時,發現的一個疑惑:,生成的Makefile連結庫路徑下如果有動態庫和靜態庫,優先選擇動態庫編譯應用 具體現象: 我最初是使用動態庫的 QtEmbedded-4.8.6-arm (編譯器選擇時,是 ./co

Linux建立、檢視、提取和修改靜態(*.a)

先說明一點,靜態庫檔案是由多個目標檔案打包而成的,在windows下靜態庫檔案的字尾是.lib,而在linux下靜態庫檔案的字尾是.a(a是archive的縮寫,也就是文件檔案)。   廢話少說,下面直接進入主題。   1.建立兩個c檔案:addition.c 和 mul

Linux環境打包成動態

在Linux環境下打包成so動態庫,被java呼叫。 一、用到了ndk技術。(略說)    1.生成標頭檔案 .h    2.C/C++介面程式碼被jni呼叫。 二、打包so動態庫如下: 1.打包成副檔名為o的檔案。      g++ -fPIC -D_REENTRA

使用dd命令在Linux建立大檔案批量大小檔案生成方法

前沿:最近在開發自動從U盤拷貝大批量檔案到linux系統的的功能。由於需要幾十個G的大檔案來做測試,如果自己去找這麼多資源,然後再拷貝,非常麻煩。所以學了下dd命令,現在總結一下: 一、引數介紹 if=FILE         從FILE中讀取資料,而不是預設的標準輸入。

Linux如何檢視動態連結so檔案的依賴

最近專案用到了opencv,在測試環境編譯後生成了so檔案,在測試環境執行正常後準備在預發環境進行上線前的測試 但是System.loadLibrary(Core.NATIVE_LIBRARY_NAM

NFS: Linux 建立區域網共享資料庫讓K臺電腦同時訪問一個硬碟

Host sudo apt-get install nfs-kernel-server sudo gedit /etc/exports # /etc/exports: the access co

linux 編譯生成靜態動態

我們此處為了說明靜態庫和動態庫的編譯,會使用示例程式碼。建立  test.h, hello.cpp 和 world.cpp, 在兩個原始檔中分別實現兩個函式( 此處都是示例程式碼,檔案命名不規範,理解意思即可 )。test.h (靜態庫標頭檔案)#ifndef _TEST_