如何从DLL生成导入库(LIB文件)?

时间:2012-03-30 15:48:06

标签: windows visual-c++ dll

是否可以从DLL自动生成MSVC导入库(LIB文件)?怎么样?

5 个答案:

答案 0 :(得分:61)

你可以generate a DEF file using dumpbin /exports

dumpbin /exports sqlite3.dll > exports.txt
echo LIBRARY SQLITE3 > sqlite3.def
echo EXPORTS >> sqlite3.def
for /f "skip=19 tokens=4" %A in (exports.txt) do echo %A >> sqlite3.def

图书管理员可以使用此DEF文件生成LIB:

lib /def:sqlite3.def /out:sqlite3.lib /machine:x86

所有文件名(exports.txtsqlite3.dllsqlite3.def等)都应以完整路径作为前缀。

答案 1 :(得分:13)

我知道主题已经过时,但我仍然无法在互联网上的任何地方找到脚本或批处理文件来执行此操作。所以根据Dark Falcon的回答,我制作了这个脚本,你可以保存为dll2lib.bat并运行:

REM Usage: dll2lib [32|64] some-file.dll
REM
REM Generates some-file.lib from some-file.dll, making an intermediate
REM some-file.def from the results of dumpbin /exports some-file.dll.
REM Currently must run without path on DLL.
REM (Fix by removing path when of lib_name for LIBRARY line below?)
REM
REM Requires 'dumpbin' and 'lib' in PATH - run from VS developer prompt.
REM 
REM Script inspired by http://stackoverflow.com/questions/9946322/how-to-generate-an-import-library-lib-file-from-a-dll
SETLOCAL
if "%1"=="32" (set machine=x86) else (set machine=x64)
set dll_file=%2
set dll_file_no_ext=%dll_file:~0,-4%
set exports_file=%dll_file_no_ext%-exports.txt
set def_file=%dll_file_no_ext%.def
set lib_file=%dll_file_no_ext%.lib
set lib_name=%dll_file_no_ext%

dumpbin /exports %dll_file% > %exports_file%

echo LIBRARY %lib_name% > %def_file%
echo EXPORTS >> %def_file%
for /f "skip=19 tokens=1,4" %%A in (%exports_file%) do if NOT "%%B" == "" (echo %%B @%%A >> %def_file%)

lib /def:%def_file% /out:%lib_file% /machine:%machine%

REM Clean up temporary intermediate files
del %exports_file% %def_file% %dll_file_no_ext%.exp

我确信脚本可以使用改进,但我希望它有用。

答案 2 :(得分:7)

此脚本在%1:

中传递* .dll创建* .lib
@echo off

setlocal enabledelayedexpansion
for /f "tokens=1-4" %%1 in ('dumpbin /exports %1') do (
    set /a ordinal=%%1 2>nul
    set /a hint=0x%%2 2>nul
    set /a rva=0x%%3 2>nul
    if !ordinal! equ %%1 if !hint! equ 0x%%2 if !rva! equ 0x%%3 set exports=!exports! /export:%%4
)

for /f %%i in ("%1") do set dllpath=%%~dpni
start lib /out:%dllpath%.lib /machine:x86 /def: %exports%

您可以将其命名为implib.bat并运行:implib.bat C:\folder\mydll.dll生成C:\ folder \ mydll.lib

答案 3 :(得分:4)

  

是否可以从DLL自动生成MSVC导入库(LIB文件)?怎么样?

除了Dark Falcon的回答,微软还在How To Create Import Libraries Without .OBJs or Source发布了程序。

微软的第一个程序与Dark Falcon相同。第二个过程有点麻烦,但它显示了如何使用存根使用目标文件。它适用于不同的调用约定和类。

以下是KB的第二个程序:

  1. 在原型或声明中使用“__declspec(dllimport)”时,将其更改为“__declspec(dllexport)”。
  2. 对于不返回值的函数,对于C源代码中的C函数,以及C ++源代码中的C函数(与'extern“C”'构造一起使用),替换用于终止函数原型的分号配对花括号(“{}”)。
  3. 对于返回值的C ++函数(全局或成员),必须为函数创建一个虚拟主体,并返回正确类型的虚拟值。 (函数中没有return语句是非法的。)这也适用于类成员函数。请记住,此过程的目的是欺骗LIB实用程序生成正确的导入库,因此这些虚拟实体不起作用。
  4. 对于C ++类,只要在编译时禁用函数内联,就可以通过在类声明中使用原型来存根成员函数。
  5. 函数参数通常只是由头文件中的类型指定。例如,Geta(int)。添加虚函数体Geta(int x)时,必须指定伪参数标识符。否则,将生成错误C2055。

答案 4 :(得分:4)

对于那些使用Linux并想为MinGW生成的.dll创建适当的导入库(.lib)的人,这里又涉及两个步骤:

  • 从.dll创建.def文件
  • 从.def创建.lib文件

使用MSVC,可以处理dumpbin /exports foo.dll的输出。在Linux上,您必须处理objdump -p的输出(来自binutils)。生成的module definition文件应如下所示:

LIBRARY foo.dll
EXPORTS
    your_symbol @1
     another_symbol @2
     ; ... et cetera

要将.def文件转换为.lib文件,请使用llvm-dlltool(MinGW(binutils)dlltool不适合)。 64位库的调用示例:

llvm-dlltool -m i386:x86-64 -d foo.def -l foo.lib

说明:

  • -m i386:x86-64:生成64位库。如果您需要一个32位库,请使用-m i386
  • -d foo.def:从文件foo.def读取导出的符号
  • -l foo.lib:将导入库写入foo.lib
  • 如果.def文件不包含LIBRARY行,则必须附加-D foo.dll选项(文件名 just ,没有目录前缀) 。

这是一个自动化脚本:

# Given libxyz-1.dll, create import library libxyz-1.lib
make_implib() {
    local machine=$1 dll="$2" dllname deffile libfile

    dllname="${dll##*/}"
    deffile="${dll%.dll}.def"
    libfile="${dll%.dll}.lib"

    # Extract exports from the .edata section, writing results to the .def file.
    LC_ALL=C objdump -p "$dll" | awk -vdllname="$dllname" '
    /^\[Ordinal\/Name Pointer\] Table$/ {
        print "LIBRARY " dllname
        print "EXPORTS"
        p = 1; next
    }
    p && /^\t\[ *[0-9]+\] [a-zA-Z0-9_]+$/ {
        gsub("\\[|\\]", "");
        print "    " $2 " @" $1;
        ++p; next
    }
    p > 1 && /^$/ { exit }
    p { print "; unexpected objdump output:", $0; exit 1 }
    END { if (p < 2) { print "; cannot find export data section"; exit 1 } }
    ' > "$deffile"

    # Create .lib suitable for MSVC. Cannot use binutils dlltool as that creates
    # an import library (like the one found in lib/*.dll.a) that results in
    # broken executables. For example, assume executable foo.exe that uses fnA
    # (from liba.dll) and fnB (from libb.dll). Using link.exe (14.00.24215.1)
    # with these broken .lib files results in an import table that lists both
    # fnA and fnB under both liba.dll and libb.dll. Use of llvm-dlltool creates
    # the correct archive that uses Import Headers (like official MS tools).
    llvm-dlltool -m "$machine" -d "$deffile" -l "$libfile"
    rm -f "$deffile"
}

# Example invocations:
make_implib i386:x86_64 usr/x86_64-w64-mingw32/sys-root/mingw/bin/libgnutls-30.dll
make_implib i386 usr/i686-w64-mingw32/sys-root/mingw/bin/libgnutls-30.dll

(请注意,如果库名称超过15个字符,则llvm-dlltool中存在一个错误,该错误会生成比所需的更大的.lib文件。除了大小外,它还具有全部功能。该问题由{{ 3}})

经过测试:

    LLVM 7.0.0-1(Arch Linux)中的
  • llvm-dlltool
  • binutils 2.31.1-3(Arch Linux)中的objdump
  • 来自binutils-mingw-w64-x86 64_2.30-7ubuntu1 + 8ubuntu1(Ubuntu 18.04)的
  • dlltool
  • Visual Studio 2015 14.00.24215.1(Windows 7)中的
  • link.exe