web-dev-qa-db-ja.com

DLLからインポートライブラリ(LIBファイル)を生成する方法は?

DLLからMSVCインポートライブラリ(LIBファイル)を自動生成することはできますか?どうやって?

51
Albert

dumpbin/exportsを使用してDEFファイルを生成

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など)の前にフルパスを追加する必要があります。

62
Dark Falcon

トピックが古いことは知っていますが、これを行うためのインターネット上のどこにもスクリプトまたはバッチファイルが見つかりませんでした。そこで、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

スクリプトは改善を使用できると確信していますが、それが役立つことを願っています。

13
Conrad Poelman

このスクリプトは、%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を生成します

8
vyshulga

Linuxを使用していて、MinGWによって生成された.dllに適切なインポートライブラリ(.lib)を作成したい場合は、2つの手順が必要です。

  • .dllから.defファイルを作成する
  • .defから.libファイルを作成する

MSVCを使用すると、dumpbin /exports foo.dllの出力を処理できます。 Linuxでは、objdump -p(binutilsから)の出力を処理する必要があります。生成された モジュール定義 ファイルは次のようになります。

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

.defファイルを.libファイルに変換するには、llvm-dlltoolを使用します(MinGW(binutils)dlltoolnotに適しています)。 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

(llvm-dlltoolには、ライブラリ名が15文字より長い場合に必要以上に大きな.libファイルを生成するバグがあることに注意してください。サイズを除けば、完全に機能します。これは https ://reviews.llvm.org/D5586

テスト済み:

  • lLVM 7.0.0-1のllvm-dlltool(Arch Linux)
  • binutils 2.31.1-3のobjdump(Arch Linux)
  • binutils-mingw-w64-x86 64_2.30-7ubuntu1 + 8ubuntu1のdlltool(Ubuntu 18.04)
  • visual Studio 2015 14.00.24215.1(Windows 7)のlink.exe
5
Lekensteyn

DLLからMSVCインポートライブラリ(LIBファイル)を自動生成することは可能ですか?どうやって?

Dark Falconの回答に加えて、Microsoftは 。OBJまたはソースなしでインポートライブラリを作成する方法 で手順を公開しています。

Microsoftの最初の手順は、Dark Falconの手順と同じです。 2番目の手順はもう少し面倒ですが、スタブを使用してオブジェクトファイルでそれを行う方法を示しています。異なる呼び出し規約とクラスで動作します。

KBの2番目の手順は次のとおりです。

  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
jww