2015-01-10 2 views
0

Я новичок в C++, и мне нелегко получить ссылки на мои dll. Я пытался заставить его работать на пару дней, но некоторые объяснения, которые я нашел, часто ссылаются на выполнение x или y, но не говорите мне , как делать x или y. Поскольку я не ветеран C++, мне нужен кто-то, чтобы пройти через меня. То, что я хочу сделать, это следующее:Как настроить многопроектное решение на C++?

MySolution 
    MyExe (Win32 .exe) 
     Main.h 
     Main.cpp 
      (constructs ImplementationB calls the methods as defined by InterfaceA, then deletes the instances) 
      (calls/fills HelperC.Foobar) 
    MyInterfaces (dll) 
     InterfaceA.h 
      ~InterfaceA(); 
      virtual void DoSomething(); 
    MyUtils (dll) 
     HelperC.h 
      static float Foobar; 
     HelperD.cpp 
      float HelperC::Foobar = 1.0f; 
    MyImplementations (dll) 
     ImplementationB : InterfaceA 
      (uses the value from HelperC.Foobar) 

В MyExe и MyImplementations проекты содержат большую часть исполняемого кода. Но мне нужен интерфейс, поэтому мне нужен проект интерфейса (MyInterfaces). Мне нужны вспомогательные классы, которые должны быть доступны как из MyExe, так и MyImplementations, следовательно MyUtils. Я хотел бы, чтобы этот вспомогательный класс был статически доступен, хотя он не является обязательным.

У меня была компиляционная версия, прежде чем я начал добавлять MyUtils с классом HelperC. Мне пришлось пометить интерфейс деструктора __declspec(dllexport), а также метод DoSomething. Я также должен был пометить конструктор ImplementationB, чтобы создать экземпляр с MyExe, что имеет смысл. Однако, когда я попытался пометить весь класс (как реализацию, так и интерфейс) с помощью __declspec(dllexport), пример не будет компилироваться (что делает не смысл).

Из того, что я читал, наличие статических полей в dll и использование их из внешнего кода на самом деле не очень хорошо работает. Таким образом, в качестве альтернативы я сделал Foobar нестатическим и передал экземпляр HelperC в метод, как описано в InterfaceA. Поскольку я уже получил простые классы для работы, я подумал, что это тоже должно работать. Однако теперь компилятор бросает ошибки на конструкторе ImplementationB (LNK2019).

Вкратце: я получаю ошибки ссылок повсюду в разделах, которые не имеют ничего общего с моими изменениями, и есть небольшая документация, описывающая конкретные шаги, которые необходимо выполнить, чтобы получить простую ссылку на dll для работы ,
Может кто-то указать, что мне нужно добавить, и где мне нужно добавить его, чтобы он скомпилировался? Кроме того, некоторые из них делают и не говорят о ссылках на C++ dll, которые очень помогли бы (например, не использовать статику в проектах).

+1

Это больше похоже на вопрос * Microsoft Visual Studio *, чем на вопрос * C++ *. – user3553031

+0

Извините, вы частично верны. Существует аспект Visual Studio, но большая его часть относится к синтаксису C++. Добавление ссылки в VS не так уж сложно, но проблема с ссылкой на работу (т. Е. Выставлять код) является проблемой. – Beijerinc

+0

Обычно вы используете макрос, который вычисляет '__declspec (dllexport)' при построении DLL и '__declspec (dllimport)' при использовании dll. – drescherjm

ответ

0

После долгих копаний я узнал, что виновником была волшебная настройка проекта. Он называется Ignore Import Library и находится по адресу Project Properties->Linker->General и по умолчанию установлен в Yes, в то время как он должен быть установлен в No в большинстве случаев. Параметр указывает исполняемому проекту использовать lib-файл dll во время компиляции. Это все еще звучит странно для меня (звучит как дубликат сборки), но, насколько я понимаю, файл lib описывает как для связи с dll. Если ваша dll создает lib во время сборки, вы, вероятно, захотите установить значение No.

Я также узнал, что, чтобы быть в состоянии использовать HelperC класс как статически доступный помощник, я должен использовать dllimport в сочетании с macro trick, как описано @drescherjm. Объявление dllimport всегда необходимо, чтобы иметь возможность использовать члены данных в библиотеках (статические классы классов или глобально определенные переменные). Он также может применяться к функциям, хотя это и не требуется, и в этом случае он обеспечивает небольшое повышение производительности при подключении библиотеки.

Для полноты моей структуры проекта после того, как заставить его работать:

MySolution 
    MyExe (Win32 .exe, Debugger Type=Mixed) 
     Main.h 
     Main.cpp 
      (constructs ImplementationB calls the methods as defined by InterfaceA, then deletes the instances) 
      (calls/fills HelperC::Foobar) 
    MyInterfaces (dll, Ignore Import Library=Yes, because there is no .lib after building) 
     InterfaceA.h 
      class __declspec(dllexport) InterfaceA 
       ~InterfaceA() {}; 
       virtual void DoSomething() = 0; 
    MyUtils (dll, Ignore Import Library=No) 
     HelperC.h 
      class __declspec(dllimport/dllexport) HelperC // (see macro trick) 
       static float Foobar; 
     HelperD.cpp 
      float HelperC::Foobar = 1.0f; 
    MyImplementations (dll, Ignore Import Library=No) 
     ImplementationB.h 
      class __declspec(dllexport) ImplementationB : public InterfaceA 
       ImplementationB(); 
       ~ImplementationB(); 
       void DoSomething(); 
     ImplementationB.cpp 
      ImplementationB::ImplementationB() {}; 
      ImplementationB::~ImplementationB() {}; 
      ImplementationB::DoSomething() { /* Omitted */ }; 
       (uses HelperC::Foobar in implementation) 

На стороне записки: если вы добавили C++ проекта библиотек классов по умолчанию в Visual Studio, то, возможно, придется перевернуть Project Properties->Debugging->Debugger Type установки на Mixed, прежде чем вы сможете установить/использовать точки останова в коде dll. См. this.

Надеюсь, это поможет другим людям, которые борются с dll в C++ (и Visual Studio).

Смежные вопросы