Как сгенерировать библиотеку импорта (LIB-файл) из DLL? - PullRequest
50 голосов
/ 30 марта 2012

Можно ли автоматически создать библиотеку импорта MSVC (LIB-файл) из DLL?Как?

Ответы [ 5 ]

61 голосов
/ 30 марта 2012

Вы можете создать файл DEF, используя 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.txt, sqlite3.dll, sqlite3.def и т. Д.) Должны начинаться с полных путей.

13 голосов
/ 11 июня 2016

Я знаю, что тема старая, но я все еще не мог найти сценарий или командный файл в Интернете, чтобы сделать это. Итак, основываясь на ответе 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 /6079524/kak-sgenerirovat-biblioteku-importa-lib-fail-iz-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

Я уверен, что скрипт может использовать улучшения, но я надеюсь, что это полезно.

8 голосов
/ 07 октября 2016

Этот сценарий создает * .lib из * .dll, переданной в% 1:

@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

4 голосов
/ 18 декабря 2018

Для тех, кто работает в Linux и хочет создать соответствующую библиотеку импорта (.lib) для .dll, созданной MinGW, здесь снова нужно выполнить два шага:

  • Создать файл .deffrom .dll
  • Создать .lib файл из .def

Используя 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) dlltool is не подходит).Пример вызова для 64-битной библиотеки:

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

Объяснение:

  • -m i386:x86-64: создать 64-битную библиотеку.Используйте -m i386, если вам нужна 32-битная библиотека.
  • -d foo.def: чтение экспортированных символов из файла foo.def
  • -l foo.lib: запись библиотеки импорта в foo.lib
  • Если файл .def не содержит строку LIBRARY, необходимо добавить параметр -D foo.dllпросто именем файла и без префикса каталога).

А вот скрипт для его автоматизации:

# 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 есть ошибка, которая выдает файл .lib большего размера, чем необходимо, если имя библиотеки длиннеечем 15 символов. Помимо размера, он полностью функционален. Это исправлено https://reviews.llvm.org/D55860)

Протестировано с:

  • llvm-dlltool из LLVM 7.0.0-1(Arch Linux)
  • objdump из binutils 2.31.1-3 (Arch Linux)
  • dlltool из binutils-mingw-w64-x86 64_2.30-7ubuntu1 + 8ubuntu1 (Ubuntu 18.04)
  • link.exe из Visual Studio 2015 14.00.24215.1 (Windows 7)
4 голосов
/ 17 ноября 2014

Можно ли автоматически создать библиотеку импорта MSVC (LIB-файл) из DLL?Как?

В дополнение к ответу Dark Falcon, Microsoft опубликовала процедуры на Как создать библиотеки импорта без .OBJ или источника .

Первая процедура Microsoft -такой же, как у Темного Сокола.Вторая процедура немного более громоздка, но показывает, как это сделать с помощью объектного файла с использованием заглушек.Он работает с различными соглашениями о вызовах и классами.

Вот вторая процедура из базы знаний:

  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.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...