很多时候我们使用的第三方库都是以dll形式提供的,大部分情况下我们可以直接使用,不过有的时候我们可能也需要将.dll导出为.lib文件。

在Windows下编程的同学,可能都知道可以使用Depends这个工具来查看dll依赖项和导出符号,却很少知道在命令行下,还有几个其他很好用的命令,分别是dumpbin和lib,这是vs安装目录下的两个程序。

win-cmd-dll

1. dumpbin

dumpbin命令的用法如下:

用法: DUMPBIN [选项] [文件]

  选项:

   /ALL
   /ARCHIVEMEMBERS
   /CLRHEADER
   /DEPENDENTS
   /DIRECTIVES
   /DISASM[:{BYTES|NOBYTES}]
   /ERRORREPORT:{NONE|PROMPT|QUEUE|SEND}
   /EXPORTS
   /FPO
   /HEADERS
   /IMPORTS[:文件名]
      /LINENUMBERS
   /LINKERMEMBER[:{1|2}]
   /LOADCONFIG
   /NOLOGO
      /OUT:filename
   /PDATA
   /PDBPATH[:VERBOSE]
   /RANGE:vaMin[,vaMax]
   /RAWDATA[:{NONE|1|2|4|8}[,#]]
   /RELOCATIONS
   /SECTION:名称
   /SUMMARY
   /SYMBOLS
   /TLS
  • /HEADERS : 可以查看dll的位数x86/x64,有哪些section。例如
D:\Program Files (x86)\lua-5.4.0_Win64_dllw6_lib>dumpbin /HEADERS lua54.dll

Microsoft (R) COFF/PE Dumper Version 12.00.40629.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file lua54.dll

PE signature found

File Type: DLL

FILE HEADER VALUES
            8664 machine (x64)
              11 number of sections
        5F3D6282 time date stamp Thu Aug 20 01:33:54 2020
           42C00 file pointer to symbol table
             E26 number of symbols
              F0 size of optional header
            2026 characteristics
                   Executable
                   Line numbers stripped
                   Application can handle large (>2GB) addresses
                   DLL
....
  • /DEPENDENTS: 可以查看依赖项,这和可视化工具Depends功能一样

  • /EXPORTS xxx.dll: 查看导出符号,即dll中包含哪些函数

  • /IMPORTS xxx.dll: 查看从依赖项中具体需要导入的函数

  • /LINKERMEMBER xxx.lib: 可以查看静态导入库中导入了哪些函数

这里我们需要制作dll对应的lib静态库文件,就需要先产生def文件,由/EXPORTS选项即可查看,但显示的信息不是按照def文件格式来的,需要我们手动调整:

D:\Program Files (x86)\lua-5.4.0_Win64_dllw6_lib>dumpbin /EXPORTS lua54.dll > lua54_nouse.def
Microsoft (R) COFF/PE Dumper Version 12.00.40629.0
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file lua54.dll

File Type: DLL

  Section contains the following exports for lua54.dll

    00000000 characteristics
    5F3D6282 time date stamp Thu Aug 20 01:33:54 2020
        0.00 version
           1 ordinal base
         152 number of functions
         152 number of names

    ordinal hint RVA      name

          1    0 0001C490 luaL_addgsub
          2    1 0001BE90 luaL_addlstring
          3    2 0001BEB0 luaL_addstring
          4    3 0001BEF0 luaL_addvalue
          5    4 0001ABD0 luaL_argerror
          6    5 0001B0D0 luaL_buffinit
          7    6 0001C2C0 luaL_buffinitsize
          8    7 0001B9A0 luaL_callmeta
          9    8 0001B020 luaL_checkany
...

上面的导出的lua54_nouse.def不是按照def文件格式标准来的,不要用此工具来导DEF文件。请使用如下的pexport工具。

2. pexport

这里我们介绍另一款工具: pexport。可以从这里下载pexports

这是mingw项目下的一款工具。使用方式如下:

# pexports -o xxx.dll  > xxx.def

3. lib

接下来就是使用lib命令,制作对应的lib文件了。其基本使用方法如下:

用法: LIB [选项] [文件]

  选项:

   /DEF[:文件名]
   /ERRORREPORT:{NONE|PROMPT|QUEUE|SEND}
   /EXPORT:符号
   /EXTRACT:成员名
   /INCLUDE:符号
   /LIBPATH:目录
   /LIST[:文件名]
   /LTCG
   /MACHINE:{ARM|ARM64|EBC|X64|X86}
   /NAME:文件名
   /NODEFAULTLIB[:库]
   /NOLOGO
   /OUT:文件名
   /REMOVE:成员名
   /SUBSYSTEM:{BOOT_APPLICATION|CONSOLE|EFI_APPLICATION|
         EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|
         NATIVE|POSIX|WINDOWS|WINDOWSCE}[,#[.##]]
   /VERBOSE
   /WX[:NO]

例如:

# lib /def:xxx.def /machine:x86 out/:xxx.lib 

或

# lib /def:xxx.def /machine:x64 out/:xxx.lib

以上分别为提取x86x64位的引入库文件;out为可选项,若忽略,则生成的lib引入库文件的名称同def文件名。

至此,我们就可以在MSVC编译器中,使用

#pragma comment(lib, "xxx.lib")

即可直接调用头文件中声明的函数了。



[参看]:

  1. 通过dll或def文件提取lib导入库文件

  2. dll导出def和lib文件