Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1279590
  • 博文数量: 185
  • 博客积分: 50
  • 博客等级: 民兵
  • 技术积分: 3934
  • 用 户 组: 普通用户
  • 注册时间: 2007-09-11 13:11
个人简介

iihero@ChinaUnix, ehero.[iihero] 数据库技术的痴迷爱好者. 您可以通过iihero AT qq.com联系到我 以下是我的三本图书: Sybase ASE in Action, Oracle Spatial及OCI高级编程, Java2网络协议内幕

文章分类

全部博文(185)

文章存档

2014年(4)

2013年(181)

分类: C/C++

2013-07-18 11:18:24

如若转载,请尊重个人劳动,务必注明原始出处。iihero 2008-9-28于CSDN

 

前几天,偶然从论坛里看到帖子,有人问:

手头只有oci.dll文件,似乎对应的头文件也有。但是就是找不到对应的lib文件。想让人家邮件发给他一个。

我回忆了一下,好像微软的VC开发工具包里头,有命令可以直接生成对应的lib文件,这样,对于开发人员来说,只要有相应版本的dll文件和头文件,无须对应的lib文件,一样可以隐式加载dll,生成可以执行程序。

 

其实,现在,想链接某dll,无非两种方式:

1. 编译时通过导入库,进而链接dll,Unix下则通过-l链接指令链接具体的动态库,windows下通过

   link  /MAP /SUBSYSTEM:CONSOLE /out:.exe  *.obj .lib 来链接

2. 在程序里显式的加载动态库,dlopen/LoadLibrary的API调用可以实现此任务,这时是不需要lib文件的。

 

当然,对于Unix/Linux平台而言,静态库动态库,都是通过-l指令来编译完成的。只是运行期,如果是动态库,则需要对应的.so,如果是静态库,不需要对应的.a静态库文件。

 

下面,我就介绍:已知dll文件,如何得到我们第一种方式要用到的导入库lib文件?

这里以PostgreSQL数据库的libpq为例,在%PGHOME%/bin下边有一个动态库文件libpq.dll,它是PostgreSQL客户端要用到的唯一的一个库文件。利用VC带的工具depends,我们看到它里边导出了很多API函数,如下图:

 

好,我们下边先进入Visual Studio .net 2003 command prompt,这个在你安装的VS的菜单或者对应的目录里边,一般都是一个批处理器文件:VSVars**.bat之类的,我这里就用VC6来演示,效果是一样的:

 

Microsoft Windows XP [版本 5.1.2600]
(C) 版权所有 1985-2001 Microsoft Corp.

D:/msdev/VC98/Bin>cp d:/pgsql8.3.3/bin/libpq.dll f:/t/

D:/msdev/VC98/Bin>cd /d f:/t/

F:/t>dumpbin /EXPORTS libpq.dll > libpq.txt

F:/t>more libpq.txt
Microsoft (R) COFF Binary File Dumper Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.


Dump of file libpq.dll

File Type: DLL

  Section contains the following exports for LIBPQ.dll

           0 characteristics
    484CFEC1 time date stamp Mon Jun 09 17:58:25 2008
        0.00 version
           1 ordinal base
         140 number of functions
         140 number of names

    ordinal hint RVA      name

         17    0 000011FE PQbackendPID
         36    1 000011DB PQbinaryTuples
        122    2 0000111D PQcancel
         48    3 00001325 PQclear
         72    4 000011C2 PQclientEncoding

F:/t>

 

我们要注意的一个重要的参数列ordinal列是表示右边的API在dll中的相对序号,这个在后边的def文件里头很重要。

然后使用UltraEdit等带列模式的编辑器,编辑libpq.txt,编辑成文件libpq.def,格式如下:

 

EXPORTS
PQbackendPID                     @          17 
PQbinaryTuples                   @          36 
PQcancel                         @         122 
PQclear                          @          48 
PQclientEncoding                 @          72 
PQcmdStatus                      @          42 
PQcmdTuples                      @          44 
PQconndefaults                   @           3 
PQconnectPoll                    @          79 
PQconnectStart                   @          80 
PQconnectdb                      @           1 
PQconnectionNeedsPassword        @         140 
PQconnectionUsedPassword         @         138 
PQconninfoFree                   @          78 
PQconsumeInput                   @          26 
PQdb                             @           7 
PQdescribePortal                 @         134 
PQdescribePrepared               @         133 
PQdisplayTuples                  @          51 
PQdsplen                         @         112 
PQencryptPassword                @         128 
PQendcopy                        @          31 
PQenv2encoding                   @          73 
PQerrorMessage                   @          15 
PQescapeBytea                    @          89 
PQescapeByteaConn                @         127 
PQescapeString                   @          88 
PQescapeStringConn               @         126 
PQexec                           @          21 
PQexecParams                     @         101 
PQexecPrepared                   @         110 
PQfformat                        @         109 
PQfinish                         @           4 
PQflush                          @          81 
PQfmod                           @          41 
PQfn                             @          32 
PQfname                          @          37 
PQfnumber                        @          38 
PQfreeCancel                     @         121 
PQfreeNotify                     @          87 
PQfreemem                        @          95 
PQfsize                          @          40 
PQftable                         @         107 
PQftablecol                      @         108 
PQftype                          @          39 
PQgetCancel                      @         120 
PQgetCopyData                    @         105 
PQgetResult                      @          24 
PQgetisnull                      @          47 
PQgetlength                      @          46 
PQgetline                        @          27 
PQgetlineAsync                   @          29 
PQgetssl                         @         114 
PQgetvalue                       @          45 
PQhost                           @          10 
PQinitSSL                        @         124 
PQisBusy                         @          25 
PQisnonblocking                  @          82 
PQisthreadsafe                   @         129 
PQmakeEmptyPGresult              @          49 
PQmblen                          @          64 
PQnfields                        @          35 
PQnotifies                       @          22 
PQnparams                        @         131 
PQntuples                        @          34 
PQoidStatus                      @          43 
PQoidValue                       @          71 
PQoptions                        @          13 
PQparameterStatus                @          97 
PQparamtype                      @         132 
PQpass                           @           9 
PQport                           @          11 
PQprepare                        @         118 
PQprint                          @          50 
PQprintTuples                    @          52 
PQprotocolVersion                @          98 
PQputCopyData                    @         103 
PQputCopyEnd                     @         104 
PQputline                        @          28 
PQputnbytes                      @          30 
PQregisterThreadLock             @         125 
PQrequestCancel                  @           6 
PQresStatus                      @          66 
PQreset                          @           5 
PQresetPoll                      @          83 
PQresetStart                     @          84 
PQresultErrorField               @         106 
PQresultErrorMessage             @          65 
PQresultStatus                   @          33 
PQsendDescribePortal             @         136 
PQsendDescribePrepared           @         135 
PQsendPrepare                    @         119 
PQsendQuery                      @          23 
PQsendQueryParams                @         102 
PQsendQueryPrepared              @         111 
PQserverVersion                  @         113 
PQsetClientEncoding              @          85 
PQsetErrorVerbosity              @          99 
PQsetNoticeProcessor             @          20 
PQsetNoticeReceiver              @         100 
PQsetdbLogin                     @           2 
PQsetnonblocking                 @          86 
PQsocket                         @          16 
PQstatus                         @          14 
PQtrace                          @          18 
PQtransactionStatus              @          96 
PQtty                            @          12 
PQunescapeBytea                  @          94 
PQuntrace                        @          19 
PQuser                           @           8 
appendBinaryPQExpBuffer          @          74 
appendPQExpBuffer                @          91 
appendPQExpBufferChar            @          68 
appendPQExpBufferStr             @          75 
createPQExpBuffer                @          77 
destroyPQExpBuffer               @          76 
enlargePQExpBuffer               @         130 
initPQExpBuffer                  @          69 
lo_close                         @          54 
lo_creat                         @          58 
lo_create                        @         123 
lo_export                        @          62 
lo_import                        @          61 
lo_lseek                         @          57 
lo_open                          @          53 
lo_read                          @          55 
lo_tell                          @          59 
lo_truncate                      @         137 
lo_unlink                        @          60 
lo_write                         @          56 
pg_char_to_encoding              @         115 
pg_encoding_to_char              @          92 
pg_utf_mblen                     @          93 
pg_valid_server_encoding         @         116 
pg_valid_server_encoding_id      @         139 
pgresStatus                      @          63 
pqsignal                         @         117 
printfPQExpBuffer                @          90 
resetPQExpBuffer                 @          70 
termPQExpBuffer                  @          67

接着使用lib命令即可生成对应的导入库及导出文件libpq.lib和libpq.exp,libpq.lib文件你终于可以得到了。

F:/t>lib /def:libpq.def
Microsoft (R) Library Manager Version 6.00.8447
Copyright (C) Microsoft Corp 1992-1998. All rights reserved.

LIB : warning LNK4068: /MACHINE not specified; defaulting to IX86
   Creating library libpq.lib and object libpq.exp

F:/t>dir libpq.*
 驱动器 F 中的卷没有标签。
 卷的序列号是 4CDC-CD55

 F:/t 的目录

2008-09-28  10:44             6,868 libpq.def
2008-09-28  10:36           167,936 libpq.dll
2008-09-28  10:46            16,299 libpq.exp
2008-09-28  10:46            28,488 libpq.lib
2008-09-28  10:37             6,268 libpq.txt
               5 个文件        225,859 字节
               0 个目录  1,673,240,576 可用字节

F:/t>

这个文件拿到你的vc6程序当中,直接可以使用。

当然如果是用vc7, vc71, vc8, vc9,那就拿对应命令行环境控制台窗口进去执行上述命令就可以了。

当然,上述方法,一样适用于C++生成的dll。只不过那些导出符号可读性不会那么好了。

 

最后总结一下,感觉,长期以来,我们习惯了使用微软的Visual Studio IDE,对于普通的命令行使用,反而感到有些茫然,这种现象不太正常,其实,应该像在Unix平台下边一样,学会使用基础的编译命令和makefile的手动编写,那样,你完全可以脱离编译器,使用gvim等编辑器,进行开发,这样反而更能加深对编译链接生成可执行码,有一个比较清晰的思路。

 

好像新的vc9里头,dll文件中可以有强链接,即,它能指定自己依赖的dll的全路径,那么有些东西是不是发生变化,还有待进一步验证。但是对于传统的dll(相信工业级软件不至于傻到所有dll全用vc9的最新特性来生成),上述方法,依然是一个补救措施。

阅读(3615) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~