在window平台下模拟Liunx使用GCC环境进行编译C的SO库

来源:互联网 发布:php取对象的值 编辑:程序博客网 时间:2024/05/21 12:49
在Liunx下的文件:

.o,是目标文件,相当于windows中的.obj文件
.so 为共享库, 是shared object,用于动态连接的,和dll差不多
.a为静态库, 是好多个.o合在一起,用于静态连接
.la为libtool自动生成的一些共享库, vi编辑查看

 

先打开VS2008 新建一个win32 控制台工程,然后新建两个文件(mathunits.h和mathunits.c)文件内容如下:

mathunits.h

[cpp] view plaincopy
  1. #ifndef MATHUNITS_H  
  2. #define MATHUNITS_H  
  3.   
  4. int add(int a,int b);  
  5. int sub(int x,int y);  
  6. void WriteSysLog(char *str);  
  7.   
  8. #endif  


mathunits.c

[cpp] view plaincopy
  1. #include "mathunits.h"  
  2. #include "time.h"  
  3. #include "stdio.h"  
  4. #include "stdlib.h"  
  5.   
  6.   
  7. int add(int a,int b)  
  8. {  
  9.     return a + b;  
  10. }  
  11.   
  12. int sub(int a,int b)  
  13. {  
  14.     return a - b;  
  15. }  
  16.   
  17. void WriteSysLog(char *str)  
  18. {  
  19.     char buf[512];  
  20.     long MAXLEN = 10*1024*1024;//10MB  
  21.     time_t timep;   
  22.     FILE *fp = NULL;  
  23.     struct tm *p;   
  24.   
  25.     time(&timep);   
  26.     p = localtime(&timep);   
  27.     memset(buf,0,sizeof(buf));  
  28.     sprintf(buf,"%d-%d-%d %d:%d:%d : ",(1900+p->tm_year),(1+p->tm_mon),\  
  29.         p->tm_mday,p->tm_hour, p->tm_min, p->tm_sec); //星期p->tm_wday  
  30.     strcat(buf,str);  
  31.     strcat(buf,"\r\n");  
  32.   
  33.     fp = fopen("./syslog.log","r");  
  34.     if(fp==NULL)  
  35.     {  
  36.         fp = fopen("./syslog.log","w+");  
  37.     }  
  38.     else  
  39.     {  
  40.         fseek(fp,0,2);  
  41.         if(ftell(fp) >= MAXLEN)  
  42.         {  
  43.             fclose(fp);  
  44.             fp = fopen("./syslog.log","w+");  
  45.             //大于10MB则清空原日志文件  
  46.         }  
  47.         else  
  48.         {  
  49.             fclose(fp);  
  50.             fp = fopen("./syslog.log","a");  
  51.         }  
  52.     }  
  53.     fwrite(buf,1,strlen(buf),fp);  
  54.     fflush(fp);  
  55.     //fsync(fileno(fp));  
  56.     fclose(fp);  
  57. }  


然后在主函数进行测试试用。(注:这是在VS2008 环境下的main)

[cpp] view plaincopy
  1. #include "stdafx.h"  
  2. #include "stdlib.h"  
  3. #include "mathunits.h"  
  4.   
  5.   
  6. int _tmain(int argc, _TCHAR* argv[])  
  7. {  
  8.     int c = add(7,9);  
  9.   
  10.     printf("c = %d\n",c);  
  11.   
  12.     c = sub(8,19);  
  13.   
  14.     printf("c = %d\n",c);  
  15.   
  16.     WriteSysLog("test log out.");  
  17.   
  18.     system("pause");  
  19.     return 0;  
  20. }  

在编译前记得先将VS2008 的配置要设为C的编译。

1、以免产生C/C++的编译冲突,先关闭预编译头:在项目上右建--》属性--》配置属性--》C/C++--》预编译头,设置为不使用预编译头。


2、设置为编译为C代码。在项目上右建--》属性--》配置属性--》C/C++--》高级--》编译为--》编译为 C 代码(/TC)

以上完成后,可以在VS下编译看看有没有问题。如果有问题自己处理一下BUG了。无问题的话就OK。

 

下面将使用GCC进行编译:

将(mathunits.h和mathunits.c)拷到一个简单的目录这里以F:\SO 作讲解,这步不是必须的,可以不移动文件。

运行CygWin.bat,将弹出命令行空口

设置编译路径到.h和.c的路径(F:\so)

输入cd /cygdrive/f/so 回车

下面先将.c文件编译为.o文件,再通过o文件编译成为静态库(.a)文件

gcc -c mathunits.c 回车,然后可以使用ls命令查看编译的文件。

图片中有些警告还有ls后有一个cmain.c这些先不理会,警告是因为我的c代码中用到了一些旧接口的函数。而cmain.c是我预先放到f:\so中的main测试文件,后面用到。

cmain.c

[cpp] view plaincopy
  1. #include "stdio.h"  
  2. #include "mathunits.h"  
  3.   
  4. int main(int agrc,char *argv){  
  5.  int c = add(7,9);  
  6.   
  7.     printf("c = %d\n",c);  
  8.   
  9.     c = sub(8,19);  
  10.   
  11.     printf("c = %d\n",c);  
  12.   
  13.     WriteSysLog("ok,good");  
  14.   
  15.     return 0;  
  16. }  

再将.o文件编译为.a静态库文件。

ar -crv libunits.a mathunits.o

说明:其中libunits为自命名的,以lib为前缀。

a:库名格式lib<name>.a,例如libmytest.a     

 b:ar命令创建静态库文件
d -----从指定的静态库文件中删除文件
m -----把文件移动到指定的静态库文件中
p -----把静态库文件中指定的文件输出到标准输出
q -----快速地把文件追加到静态库文件中
r -----把文件插入到静态库文件中
t -----显示静态库文件中文件的列表
x -----从静态库文件中提取文件

 

ar 命令的命令行格式如下:
ar [-]{dmpqrtx}[abcfilNoPsSuvV] [membername] [count] archive files... 参数archive定义库的名称, files是库文件中包含的目标文件的清单, 用空格分隔每个文件

下面测试一下静态库的使用,将前面的哪个cmail.c放到f:\so目录下。

在GCC下进行静态库的连接使用。

命令:

方法一:

gcc  -o testlib cmain.c -L. -lunits

说明:testlib为最终编译出来的EXE文件名。 -L.为搜索当前路径(.)下的.a文件,即表示在当前目录中搜索连接库。

-lunits其中units为库的名去掉了lib前缀.

-l:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上lib,后面加上.so来确定库的名称,如果是静态库,在后面加上.a来确定名称.

运行一下输出的testlib.exe

输入命令:

./testlib 回车

为了验证静态库在使用时是否被成功集入(链接到EXE)程序中。我们将删除libunits.a文件后再来运行./testlib。

如果成功输出则表示成功集入。

 

静态库使用的方法二:

gcc cmain.c libunits.a -o testlib

方法三:先将cmain.c生成.o文件,再生成可执行文件。

gcc  -c cmain.c    //生成.o

gcc  -o testlib cmain.o  libunits.a

 

以上是生成静态库.a文件。

下面是生成动态库.so文件。

在有.o文件之后就可以进行打so了。

命令:

gcc  -shared -fPCI -o libdyunits.so mathunits.o

其中-o是不可少;

-shared 该选项指定生成动态连接库(让连接器生成T类型的导出符号表,有时候也生成弱连接W类型的导出符号),不用该标志外部程序无法连接。相当于一个可执行文件
-fPIC 表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的所以动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。

-L. 表示要连接的库在当前目录中;(多个库:在编译命令行中,将使用的静态库文件放在源文件后面就可以了。比如:gcc -L/usr/lib myprop.c libtest.a libX11.a libpthread.a -o myprop
其中-L/usr/lib指定库文件的查找路径。编译器默认在当前目录下先查找指定的库文件,如前面的“法二 #gcc cmain.c libunits.a -o testlib”

LD_LIBRARY_PATH这个环境变量指示动态连接器可以装载动态库的路径。
当然如果有root权限的话,可以修改/etc/ld.so.conf文件,然后调用 /sbin/ldconfig来达到同样的目的,不过如果没有root权限,那么只能采用输出LD_LIBRARY_PATH的方法了。

调用动态库的时候有几个问题会经常碰到,有时,明明已经将库的头文件所在目录 通过 “-I” include进来了,库所在文件通过 “-L”参数引导,并指定了“-l”的库名,但通过ldd命令察看时,就是死活找不到你指定链接的so文件,这时你要作的就是通过修改 LD_LIBRARY_PATH或者/etc/ld.so.conf文件来指定动态库的目录。通常这样做就可以解决库无法链接的问题了。

另:

从上述可知,如何找到生成的动态库有3种方式:

(1)把库拷贝到/usr/lib和/lib目录下。

(2)在LD_LIBRARY_PATH环境变量中加上库所在路径。

例如动态库libhello.so在/home/example/lib目录下:

$export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/home/example/lib

(3) 修改/etc/ld.so.conf文件,把库所在的路径加到文件末尾,并执行ldconfig刷新。这样,加入的目录下的所有库文件都可见。

 

动态库的连接使用跟静库使用命令一样,如果静态库和动态库同时存在,优先调用动态库。

gcc cmain.c libdyunits.so -o testlib

 

使用下面命令时有个错误,小弟未能解决。试了几个网上的解决方法均不能解除。

上以是路径设置问题引起。

1:在unix/linux环境下
  1.1:生成.o文件
  gcc -I/usr/lib/j2sdk1.5-ibm/include -fPIC -c example.c 
  1.2:生成动态库.so文件
  gcc -shared -WI -soname example.o -o  libexample.so
  2:在windows环境下
  2.1:生成.o文件
  gcc -c -I"D:\Program Files\Java\jdk1.6.0_10\include" -I"D:\Program Files\Java\jdk1.6.0_10\include\win32" -o Hello.o Hello.c
  2.2:生成dll文件
  gcc -I"D:\Program Files\Java\jdk1.6.0_10\include" -Wl,--add-stdcall-alias -shared -o Hello.dll Hello.o

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 笔记本电源已接通未充电怎么办 电源已接通未充电怎么办 遮盖纹身好了颜色淡了怎么办 致炫方向盘变重怎么办 xp音频图标没了怎么办 狙击精英3没子弹怎么办 干活干的手腕疼怎么办 干了活不给钱怎么办 干了活要不到钱怎么办 活干完了钱不给怎么办 微信语音聊天音量很小怎么办 一手软件崩溃钱卡住了怎么办 身上皮肤很黑怎么办?好想穿短裙 家里有很多小飞虫怎么办 家里有垃圾中飞出虫子怎么办 雷蛇笔记本很烫怎么办 登录监控器的账号锁了怎么办 悦借钱登录账号被锁怎么办 365账号登录被锁怎么办 台式电脑cpu温度过高怎么办 UG2.0打不开错误—15怎么办 键盘空格键删除键失灵怎么办 耳麦检测声音不分左右怎么办 吃生萝卜胃疼怎么办 幼兔拉稀怎么办没精神 自酿米酒酸了怎么办 用冰敷脸感觉红烫了怎么办 吃了海兔的内脏怎么办 吃了鱿鱼的吸盘怎么办 想开个烧烤店没学过怎么办 墨鱼汁弄衣服上怎么办 干鱿鱼泡开发黄怎么办 吃了芥末胃疼怎么办 手撕鱿鱼咸了怎么办 孕妇吃了点芥末怎么办 葡萄酒上面有一层白霉怎么办 手机一不小心把视频删了怎么办 柑橘7月份果实小怎么办 鹦鹉鱼身上有小白点怎么办 鹦鹉鱼身上烂了怎么办 红鹦鹉鱼变黑了怎么办