如何通过dll文件生成对应的lib文件(开发人员的一个小技巧)

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

 

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

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

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

 

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

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

   link  /MAP /SUBSYSTEM:CONSOLE /out:<file>.exe  *.obj <abc>.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的最新特性来生成),上述方法,依然是一个补救措施。

 

posted @ 2008-09-28 10:18  张长胜  阅读(332)  评论(0编辑  收藏  举报