Принудительный экспорт символов с помощью MSVC - PullRequest
7 голосов
/ 14 января 2009

У меня есть приложение и несколько плагинов в DLL-файлах. Плагины используют символы из приложение через экспортную библиотеку. Приложение связывает несколько статических библиотек, и именно отсюда происходит большинство символов. Это работает нормально, пока приложение использует символ. Если символ там не используется, я получаю ошибки компоновщика при компиляции DLL.

Как заставить экспорт символов, используемых только в плагинах?

Для запуска экспорта я пробовал что-то вроде этого:

    class MyClassExporter
    {
        MyClass mInstance;
    public:
        MyClassExporter() {}
    };
    static MyClassExporter TheMyClassExporter;

в одной из статических библиотек, из которой сделано приложение для форсирования экспорта, который не сработал.

В ответ Грегу (спасибо за ответ) и уточняю: класс, для которого я хочу форсировать экспорт, это MyClass (для которого определен __declspec (...), в зависимости от того, хотите ли я экспортировать или импортировать). MyClassExport был моей попыткой принудительно включить в приложение неиспользуемые (с точки зрения приложения) символы. Я хочу «дотронуться» до символов, чтобы компоновщик распознал их как использованные и включил их в приложение, чтобы он в свою очередь мог экспортировать их в мои плагины. Связывать статические библиотеки в плагины не вариант, так как они содержат синглеты, которые будут дублироваться (у приложений и DLL есть свои копии статических переменных).

Ответы [ 5 ]

3 голосов
/ 18 января 2009

Директива / INCLUDE может использоваться, чтобы заставить компоновщик MSVC включать символ. В качестве альтернативы, / OPT: NOREF может использоваться для отключения удаления неиспользуемых символов в целом.

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

3 голосов
/ 15 января 2009

Вы, вероятно, хотите посмотреть на __declspec (экспорт / импорт)

#ifdef DLL_EXPORTING
#define WHDLL __declspec(dllexport)
#else
#define WHDLL __declspec(dllimport)
#endif

При связывании статического модуля в dll он будет вводить только используемый код. Я никогда не импортировал материал из статической библиотеки, чтобы просто экспортировать его.
Возможно, вам просто нужно пометить его как экспортируемый в dll при компиляции статической библиотеки.

Но это напоминает мне о помещении контейнеров std в экспортируемые классы и использовании некоторых хитростей в msvc для экспорта «экземпляра» специализированного контейнера. код шаблона похож на ваш статический код (по моему мнению)

например, без шаблона вы получаете предупреждения, код шаблона не экспортируется для поддержки класса - это, как я понимаю, MSVC

template class DLL_EXPORTING std::auto_ptr<wxCursor>;
class DLL_EXPORTING imageButton : public wxWindow
{
    std::auto_ptr<wxCursor> m_Cursor;
};
2 голосов
/ 13 сентября 2012

Опция «Использовать входы зависимостей библиотеки» делает свое дело в VS2005!

Этот параметр можно найти в разделе «Свойства конфигурации» -> «Линкер» -> «Общие» -> «Использовать входы зависимостей библиотеки». Установите в «true» для принудительной привязки во ВСЕХ символах и коде, объявленном в каждой LIB, указанной в качестве входных данных для проекта.

Вы можете сделать следующее, чтобы получить символ для экспорта из DLL: определить LIB_EXPORTS в проекте библиотеки и ничего в проекте DLL или в проекте клиента DLL.

#ifdef LIB_EXPORTS
#define DLLAPI __declspec(dllexport)
#else
#define DLLAPI __declspec(dllimport)
#endif

Оказывается, нет необходимости #include каких-либо заголовков из проекта LIB при компиляции проекта DLL; просто укажите LIB в качестве входных данных компоновщика. Однако, если вам нужно использовать код LIB из DLL, вам нужно #define DLLAPI как пустой макрос; установка символа (символов) в dllexport или dllimport приведет к ошибке или предупреждению соответственно.

2 голосов
/ 18 января 2009

Что я пытался решить, так это:

  1. построить статическую библиотеку с функцией void afunction( int ).
  2. сборка dll, связанная со статической библиотекой, экспортирующая afunction.
  3. построить exe, используя символ afunction.

Как? Поскольку компоновщику может быть приказано экспортировать функции с использованием директивы __declspec(dllexport), dll нужно всего лишь объявить символ для экспорта таким образом.

В библиотеке есть заголовок "afunction.h" и сопроводительный файл cpp, содержащий тело функции:

// stat/afunction.h
namespace static_lib { void afunction(int); }


// stat/afunction.cpp
#include "afunction.h"
namespace static_lib { void afunction(int){ } }

В dll есть включаемый файл "irect.h ", содержащий объявление экспортируемой функции. DLL имеет зависимость от времени соединения со статической библиотекой. (Параметры компоновщика: вход / дополнительные зависимости: "static_library.lib")

// dll/indirect.h
namespace static_lib {
  __declspec( dllexport ) void afunction(int);
}

Исполняемый файл содержит только косвенно включенный файл:

#include <dll/indirect.h>
int main() { static_lib::afunction(1); }

И угадайте что? Он компилирует, связывает и даже запускает!

1 голос
/ 16 декабря 2010

Существует некоторое обсуждение этой проблемы на MSDN, которое было довольно полезным. Как выясняется, в этом случае / OPT: NOREF не особенно полезен. / INCLUDE может работать, но может быть трудно автоматически определить, что нужно / INCLUDEd. К сожалению, серебряной пули нет.

http://social.msdn.microsoft.com/forums/en-US/vclanguage/thread/2aa2e1b7-6677-4986-99cc-62f463c94ef3

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...