注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

dingchaoqun12 的博客

上海股票期货开户

 
 
 

日志

 
 
 
 

C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客  

2012-12-24 02:55:03|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
C语言的跨平台性及库的跨平台性研究
2009-07-26 22:47:24
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://jeremiah.blog.51cto.com/539865/183560
    啥?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写个简单的测试程序说明两者的异同。
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>#include <stdio.h>
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>int main()
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>{
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>        printf("hello world\n");
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>        return 0;
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>}
   
    在MinGW和Cygwin下分别执行
gcc -o hello hello.c
./hello
    在各自的环境中,都能运行出hello world来。
    但是如果在cmd下运行Cygwin/GCC编译出来的hello.exe,却说找不到Cygwn1.dll。
650) this.width=650;" onsubmit onchange onreset onselect onunload>
   
    在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。
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>//add.h
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>int add(int, int);
 
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>//add.c    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>#include "add.h"    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>int add(int x, int y)    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>{    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>        return x + y;    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>}    
    编译生成静态库
gcc -c add.c
ar crs libadd.a add.o
    编译生成动态库
gcc -shared -o libadd.dll add.c
    这样,包含一个add函数的静态库和动态库就建立好了。
 
    在testlib下建立test.c来调用库。
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>//test.c    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>include <stdio.h>    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>#include "add.h"    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>int main()    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>{    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>    printf("result=%d\n", add(3,5));    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>    return 0;    
C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客 - dingchaoqun12 - dingchaoqun12 的博客650) this.width=650;" onsubmit onchange onreset onselect onunload>}
    执行
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
会出现问题
650) this.width=650;" onsubmit onchange onreset onselect onunload>
    主要是因为动态库的位置我们没有告诉系统。所以系统调用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的播放器。



引文来源  C语言的跨平台性及库的跨平台性研究 - 海狗哥的流媒体空间 - 51CTO技术博客
  评论这张
 
阅读(349)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017