天天看点

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