Экспорт символов в статической библиотеке, связанной с динамической библиотекой - PullRequest
1 голос

У меня есть следующий сценарий в MSVC2017:

  1. Статическая библиотека с функцией bool foo()
  2. Библиотека динамических ссылок, которая ссылается на статическую библиотеку выше
  3. Приложение, которое загружает динамическую библиотеку с использованием явного связывания во время выполнения и вызывает foo() через GetProcAddress

В статической библиотеке foo() определяется следующим образом:

extern "C" __declspec(dllexport) bool foo() 
{
    return true;   
}

Теперь, поскольку foo() не используется библиотекой динамических ссылок, ее символ не экспортируется и, следовательно, не может быть найден, когда приложение использовало GetProcAddress.

Я пробовал:

#pragma comment(linker, "/include:foo")

и:

#pragma comment(linker, "/export:foo")

Я вижу экспортированный foo()использование Dependency Walker, если я переместил определение в библиотеку динамических ссылок (не жизнеспособное решение), но я не могу экспортировать символ, когда я сохраняю определение в статической библиотеке с указанными выше переключателями компоновщика.Я предполагаю, что это потому, что символ все еще не используется, и, следовательно, все еще не экспортируется независимо от?

Мне бы хотелось найти решение как для MSVC в Windows, так и для Clang в Linux.Спасибо!

Ответы [ 2 ]

1 голос

В итоге я решил создать фиктивную функцию, которая вызвала foo(), чтобы принудительно экспортировать все символы в этом модуле компиляции.

0 голосов
/ 30 июня 2019

Вы делаете что-то не так (или, по крайней мере, не так, как вы описали в вопросе).Конечно, то, что вы разместили в своем ответе, также работает, но это только обходной путь, так как «обычный» способ должен работать.
Вот небольшой пример.

lib.cpp :

extern "C" __declspec(dllexport) bool foo() {
    return true;
}

dll.cpp :

extern "C" __declspec(dllexport) bool bar() {
    return false;
}

Вывод :

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q056330888]> sopr.bat
*** Set shorter prompt to better fit when pasted in StackOverflow (or other) pages ***

[prompt]> "c:\Install\x86\Microsoft\Visual Studio Community\2017\VC\Auxiliary\Build\vcvarsall.bat" x64
**********************************************************************
** Visual Studio 2017 Developer Command Prompt v15.9.13
** Copyright (c) 2017 Microsoft Corporation
**********************************************************************
[vcvarsall.bat] Environment initialized for: 'x64'

[prompt]> dir /b
dll.cpp
lib.cpp

[prompt]> cl /c /nologo /D_LIB /DSTATIC /Folib.obj lib.cpp
lib.cpp

[prompt]> lib /nologo /out:lib.lib lib.obj

[prompt]>
[prompt]> cl /c /nologo /DDLL /Fodll.obj dll.cpp
dll.cpp

[prompt]> link /nologo /dll /out:dll.dll dll.obj lib.lib
   Creating library dll.lib and object dll.exp

[prompt]> dir /b
dll.cpp
dll.dll
dll.exp
dll.lib
dll.obj
lib.cpp
lib.lib
lib.obj

[prompt]> dumpbin /nologo /exports dll.dll

Dump of file dll.dll

File Type: DLL

  Section contains the following exports for dll.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           1 number of functions
           1 number of names

    ordinal hint RVA      name

          1    0 00001000 bar

  Summary

        2000 .data
        1000 .pdata
        9000 .rdata
        1000 .reloc
        B000 .text

[prompt]>
[prompt]> rem Re-link dll, instructing it to include foo

[prompt]> link /nologo /dll /include:foo /out:dll.dll dll.obj lib.lib
   Creating library dll.lib and object dll.exp

[prompt]> dumpbin /nologo /exports dll.dll

Dump of file dll.dll

File Type: DLL

  Section contains the following exports for dll.dll

    00000000 characteristics
    FFFFFFFF time date stamp
        0.00 version
           1 ordinal base
           2 number of functions
           2 number of names

    ordinal hint RVA      name

          1    0 00001000 bar
          2    1 00001010 foo
  Summary

        2000 .data
        1000 .pdata
        9000 .rdata
        1000 .reloc
        B000 .text

Примечания :

  • Как я уже заметил, я использовал командную строку,но те же команды (больше аргументов) вызываются VStudio IDE
  • Добавление /include:foo (2 nd ссылка команда) также экспортирует foo (как видно из следующего dumpbin output):
    • Указание этого параметра идентично добавлению #pragma comment(linker, "/include:foo") dll.cpp - или любой файл, который напрямую передается компоновщику)
    • /export:foo не требуется, так как функция уже экспортирована с помощью __declspec(dllexport)
  • Я не прошел конец (приложение), так как foo присутствует в dumpbin Вывод достаточно (это также видно из Ходок Зависимости )

@ EDIT0 :

Youможет не делать что-то неправильно в конце концов.Глядя на [MS.Docs]: обзор LIB , он предоставляет те же опции, что и link в отношении экспорта материалов.Но они, похоже, игнорируются.

При сборке библиотеки, возможно, вы захотите указать все символы, которые будут включены во время соединения (либо через опцию, либо через #pragma comment), когда строит .lib , а не при связывании .По-видимому, они игнорируются (я проверял это), если только материал не указан в .obj файлах (или опциях), передаваемых непосредственно компоновщику.Я не знаю почему, возможно, это как-то связано с [MS.Docs]: создание библиотеки импорта и экспорта файла :

Обратите внимание, что если вы создаетеПеред тем как создать библиотеку .dll, перед созданием библиотеки DLL вы должны передать тот же набор объектных файлов, что и при создании библиотеки импорта.

В любом случае, япопытался сделать это, извлекая lib.obj из .lib (его размер отличается от того, который я использовал для создания .lib с)и передать его компоновщику, но функция все еще не была экспортирована.Как примечание, если я передам (оригинальный) lib.obj #pragma comment (linker, /include:foo) непосредственно компоновщику, он экспортирует foo .

...