C語言的跨平臺性及庫的跨平臺×××

請移步https://higoge.github.io/,全部下載資料在那個博客都能找到。謝謝。 html

這篇文章寫的太爛了,仍是別看了。git

--------------------------------------------------------------------github

    啥?C語言是跨平臺的?你們剛學C語言的時候,都知道C是不跨平臺的。C的跨平臺性從何提及?
編程

 

    呵呵,看官莫急,聽Jeremiah徐徐道來。ide

 

    本篇博客所討論的跨平臺性,是比較狹義的,主要是討論跨Windows和Linux這兩個最流行的操做系統,確切的說,是跨VC和gcc這兩大編譯器。在這也只是淺談一下,不作太深刻的研究。函數

 

    主要內容以下:
    1. C語言的跨平臺性
    2. MinGW及Cygwin
    3. GCC製做動態庫及靜態庫及調用方法
    4. VC++製做的靜/動態庫與GCC製做的動靜態庫相互替換
測試


    1. C語言的跨平臺性
    你們也都知道Java是跨平臺的語言,主要是由於在不一樣的系統上面安裝不一樣的JRE,也就是Java運行時環境,這樣,相同的代碼在不一樣的操做系統上面,運行的效果是同樣的。
spa

 

    其實Jeremiah所謂的跨平臺性,跟Java的這種機制是相似的。主要是編譯器GCC的跨平臺性。操作系統

 

    看過Jeremiah之前博客的人都應該知道Jeremiah主要研究的是開源項目VLC,順便研究了點FFmpeg及Live555,這些項目其實都是基於Linux開發的,可是能在Windows上運行主要是藉助了兩個環境,MinGW及Cygwin。以此類推,若是咱們基調試

於Linux作開發,想要在Windows下運行,那就用MinGW或Cygwin就okay了。Jeremiah之後也將主要從事Linux裏的C編程開發。

    2. MinGW及Cygwin
    Google "MinGW Cygwin/Gcc"會出現不少關於MinGW和Cygwin的文章。主要介紹了MinGW和Cygwin這兩個Jeremiah所謂的仿真Linux環境的異同。推薦看一下http://blog.classky.com/2008/11/27/difference-of-gcc-compiler-between-MinGW-and-cygwin/http://bbs.lupa.gov.cn/273398/viewspace-122539.html。英文的看這個http://www.delorie.com/howto/cygwin/mno-cygwin-howto.html裏面講的很是的好。

 

    在這Jeremiah寫個簡單的測試程序說明二者的異同。

InBlock.gif#include <stdio.h>
InBlock.gif
InBlock.gifint main()
InBlock.gif{
InBlock.gif        printf("hello world\n");
InBlock.gif        return 0;
InBlock.gif}

   

    在MinGW和Cygwin下分別執行

gcc -o hello hello.c
./hello

    在各自的環境中,都能運行出hello world來。

    可是若是在cmd下運行Cygwin/GCC編譯出來的hello.exe,卻說找不到Cygwn1.dll。

   

    在cygwin下編譯hello.c的時候加入參數-mno-cygwin,則cmd下運行的時候,就能夠正確的執行。

gcc -mno-cygwin -o hello hello.c
./hello

    也就是gcc -mno-cygwin編譯出來的程序能夠不須要Cygwin1.dll。這也就是爲何咱們運行編譯完的VLC的時候,沒有提示須要這個Cygwin1.dll。由於咱們在configure-vlc.sh中加入了CC="gcc -mno-cygwin" CXX="g++ -mno-cygwin"。那是否是說Cygwin的gcc -mno-cygwin與MinGW的gcc是同樣的呢?通過Jeremiah的使用,發現,仍是有些許區別的。好比我在Cygwin下用gcc -mno-cygwin編譯Live555的就會報錯,而在MinGW下編譯,就沒問題。具體緣由,尚未搞明白。可是通常的程序,仍是能夠當作等同的。

    3. GCC製做動態庫及靜態庫及調用方法
    若是是Linux的開發人員,這個東西簡直太簡單了。我這個標題主要是寫給VC++的開發人員的。由於Jeremiah接觸了一些VC++的開發人員,發現這些朋友對Linux相關的東西不是太熟悉。因此在這寫一個簡單的程序來講明Linux的庫的製做及調用。主要的編譯器仍是MinGW的Gcc或者是Cygwin的gcc -mno-cygwin。

 

    在當前目錄創建文件夾test,下面分別創建兩個文件夾lib,及testlib。

mkdir test && cd test && mkdir lib testlib

    在lib下創建add.h及add.c。

InBlock.gif//add.h
InBlock.gifint add(int, int);

 

InBlock.gif//add.c    
InBlock.gif#include "add.h"    
InBlock.gif    
InBlock.gifint add(int x, int y)    
InBlock.gif{    
InBlock.gif        return x + y;    
InBlock.gif}    

    編譯生成靜態庫

gcc -c add.c
ar crs libadd.a add.o

    編譯生成動態庫

gcc -shared -o libadd.dll add.c

    這樣,包含一個add函數的靜態庫和動態庫就創建好了。

 

    在testlib下創建test.c來調用庫。

InBlock.gif//test.c    
InBlock.gifinclude <stdio.h>    
InBlock.gif#include "add.h"    
InBlock.gif
InBlock.gifint main()    
InBlock.gif{    
InBlock.gif    printf("result=%d\n", add(3,5));    
InBlock.gif    return 0;    
InBlock.gif}

    執行

gcc -o test test.c -I../lib -L../lib -ladd
./test

    就能獲得結果

result=8

    但這只是鏈接的靜態庫。

    若是鏈接動態庫呢? VC++的開發人員都知道調用dll的方法,須要LoadLibrary及GetProcAddress這些函數一個個的把dll中的函數導入進來調用。(參考:http://tech.ddvip.com/2007-03/117395352621216.html
    可是在Linux下面就不用,調用動態庫與靜態庫是同樣同樣的。(Jeremiah很喜歡這樣的方式,吼吼)
執行

rm ../lib/libadd.a
gcc -o test test.c -I../lib -L../lib -ladd
./test

會出現問題

    主要是由於動態庫的位置咱們沒有告訴系統。因此係統調用libadd.dll的時候,找不到它在何處。


    Linux下一般的方法是配置LD_LIBRARY_PATH。

export LD_LIBRARY_PATH=~/test/lib

    可是配置這個環境變量在MinGW和Cygwin是很差用的,仍是會提示找不到libadd.dll。應該配置的環境變量是PATH。

export PATH=~/test/lib:${PATH}
echo $PATH
./test

    這樣就能獲得結果了。


    4. VC++製做的靜/動態庫與GCC製做的動靜態庫相互替換
    這樣能夠嗎?真的能夠嗎?答案是:能夠。


    Jeremiah某日腦子發神經,忽然想研究VC++編譯其與MinGW/Gcc的相互調用問題,由於這兩個環境編出來的都是Windows下的程序,確定應該存在必定的共性。並且主要是VC++靜態庫.lib和MinGW/Gcc的靜態庫.a的關係。


    通過研究,結論是:
    1) MinGW編譯生成的動態庫libadd.dll,能夠被VC++的任何一個環境調用。
    2) Mingw編譯生成的靜態庫libadd.a也能夠被被VC++的任何一個環境調用,只不過要本身手動更名字,將libadd.a改成libadd.lib就可使用了。

    3) 將上面的add.h及add.c用VC製做成一個靜態庫和一個動態庫對VC++開發人員是小菜一碟的事情,可是通過測試發現,只有VC6生成的libadd.lib及libadd.dll才能被MinGW/Gcc調用。其餘的VS版本沒有調試成功,主要是由於MinGW/Gcc和VC6都使用COFF格式,而其餘的VS版本,我不知道是啥格式。是否能夠調整到這樣的格式,還請各位VC++達人告訴我一聲。謝謝。

 

    囉囉嗦嗦了這麼些,最後的結果就是VLC的那些dll在VC++下是徹底能夠被調用到的。下一篇Jeremiah將會介紹用VC++調用libvlc.dll製做MFC的播放器。

相關文章
相關標籤/搜索