程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> C語言的跨平台性及庫的跨平台性研究

C語言的跨平台性及庫的跨平台性研究

編輯:關於C語言

    啥?C語言是跨平台的?大家剛學C語言的時候,都知道C是不跨平台的。C的跨平台性從何說起?       呵呵,看官莫急,聽Jeremiah徐徐道來。       本篇博客所討論的跨平台性,是比較狹義的,主要是討論跨Windows和Linux這兩個最流行的操作系統,確切的說,是跨VC和gcc這兩大編譯器。在這也只是淺談一下,不做太深入的研究。       主要內容如下:
    1. C語言的跨平台性
    2. MinGW及Cygwin
    3. GCC制作動態庫及靜態庫及調用方法
    4. VC++制作的靜/動態庫與GCC制作的動靜態庫相互替換

    1. C語言的跨平台性
    大家也都知道Java是跨平台的語言,主要是因為在不同的系統上面安裝不同的JRE,也就是Java運行時環境,這樣,相同的代碼在不同的操作系統上面,運行的效果是一樣的。
      其實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寫個簡單的測試程序說明兩者的異同。 #include <stdio.h>

int main()
{
        printf("hello world\n");
        return 0;
}         在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。 //add.h
int add(int, int);   //add.c    
#include "add.h"    
    
int add(int x, int y)    
{    
        return x + y;    
}    
    編譯生成靜態庫 gcc -c add.c
ar crs libadd.a add.o     編譯生成動態庫 gcc -shared -o libadd.dll add.c     這樣,包含一個add函數的靜態庫和動態庫就建立好了。       在testlib下建立test.c來調用庫。 //test.c    
include <stdio.h>    
#include "add.h"    

int main()    
{    
    printf("result=%d\n", add(3,5));    
    return 0;    
}     執行 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的播放器。

本文出自 “海狗哥的流媒體空間” 博客,請務必保留此出處http://jeremiah.blog.51cto.com/539865/183560

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved