天天看點

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

請移步https://higoge.github.io/,所有下載下傳資料在那個部落格都能找到。謝謝。 

這篇文章寫的太爛了,還是别看了。

--------------------------------------------------------------------

    啥?c語言是跨平台的?大家剛學c語言的時候,都知道c是不跨平台的。c的跨平台性從何說起?

    呵呵,看官莫急,聽jeremiah徐徐道來。

    本篇部落格所讨論的跨平台性,是比較狹義的,主要是讨論跨windows和linux這兩個最流行的作業系統,确切的說,是跨vc和gcc這兩大編譯器。在這也隻是淺談一下,不做太深入的研究。

    主要内容如下:

    1. c語言的跨平台性

    2. mingw及cygwin

    3. gcc制作動态庫及靜态庫及調用方法

    4. vc++制作的靜/動态庫與gcc制作的動靜态庫互相替換

    大家也都知道java是跨平台的語言,主要是因為在不同的系統上面安裝不同的jre,也就是java運作時環境,這樣,相同的代碼在不同的作業系統上面,運作的效果是一樣的。

    其實jeremiah所謂的跨平台性,跟java的這種機制是類似的。主要是編譯器gcc的跨平台性。

    看過jeremiah以前部落格的人都應該知道jeremiah主要研究的是開源項目vlc,順便研究了點ffmpeg及live555,這些項目其實都是基于linux開發的,但是能在windows上運作主要是借助了兩個環境,mingw及cygwin。以此類推,如果我們基

于linux做開發,想要在windows下運作,那就用mingw或cygwin就okay了。jeremiah以後也将主要從事linux裡的c程式設計開發。

    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寫個簡單的測試程式說明兩者的異同。

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

#include <stdio.h>

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

int main()

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

{

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

        printf("hello world\n");

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

        return 0;

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

}

    在mingw和cygwin下分别執行

gcc -o hello hello.c

./hello

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

    但是如果在cmd下運作cygwin/gcc編譯出來的hello.exe,卻說找不到cygwn1.dll。

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

    在cygwin下編譯hello.c的時候加入參數-mno-cygwin,則cmd下運作的時候,就可以正确的執行。

gcc -mno-cygwin -o hello hello.c

    也就是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下編譯,就沒問題。具體原因,還沒有搞明白。但是一般的程式,還是可以看成等同的。

    如果是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。

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

//add.h

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

int add(int, int);

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

//add.c    

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

#include "add.h"    

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

int add(int x, int y)    

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

{    

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

        return x + y;    

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

}    

    編譯生成靜态庫

gcc -c add.c

ar crs libadd.a add.o

    編譯生成動态庫

gcc -shared -o libadd.dll add.c

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

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

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

//test.c    

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

include <stdio.h>    

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

int main()    

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

    printf("result=%d\n", add(3,5));    

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

    return 0;    

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

    執行

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

會出現問題

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

    主要是因為動态庫的位置我們沒有告訴系統。是以系統調用libadd.dll的時候,找不到它在何處。

    linux下通常的方法是配置ld_library_path。

export ld_library_path=~/test/lib

    但是配置這個環境變量在mingw和cygwin是不好用的,還是會提示找不到libadd.dll。應該配置的環境變量是path。

export path=~/test/lib:${path}

echo $path

    這樣就能得到結果了。

    這樣可以嗎?真的可以嗎?答案是:可以。

    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的播放器。