Экспорт DLL и наследование в C ++ - PullRequest
5 голосов
/ 09 июля 2011

Я пытаюсь экспортировать класс и его базовый класс из DLL следующим образом:

#ifdef MY_EXPORTS
    #define DECLSPEC_TEST __declspec(dllexport)
#else
    #define DECLSPEC_TEST __declspec(dllimport)
#endif


class DECLSPEC_TEST BaseClass
{
  // stuff.
};

class DECLSPEC_TEST DerivedClass : public BaseClass
{
  // This class only has a constructor which initializes the class differently.

};

Но я пытаюсь использовать этот класс в другой DLL, я получаю сообщение об ошибке:

error LNK2019: unresolved external symbol 
"__declspec(dllimport) public: __thiscall DerivedClass::DerivedClass(void)"
 (__imp_??0DerivedClass@@QAE@XZ) referenced in function 
"public: __thiscall SomeOtherClass::SomeOtherClass(void)" (??0SomeOtherClass@@QAE@XZ)  

Я также посмотрел на мою экспортируемую DLL с помощью PE Explorer и не могу увидеть производный класс в списке экспорта.

Когда я пытаюсь использовать базовый класс в моей другой DLL, он работает нормально.

Что я делаю не так?

Ответы [ 7 ]

3 голосов
/ 09 июля 2011

Есть два способа загрузки DLL. Первый - ссылаться на один или несколько символов из DLL (например, имя вашего класса), предоставлять соответствующий импорт .LIB и позволить компоновщику разобраться во всем.

Второй - явная загрузка DLL через LoadLibrary.

Любой подход отлично работает для экспорта функций уровня C. Вы можете позволить компоновщику обработать его или вызвать GetProcAddress, как вы заметили.

Но когда речь идет об экспортируемых классах, обычно используется только первый подход, то есть неявная ссылка на DLL.

3 голосов
/ 09 июля 2011

Хорошо, я не знаю, как это объяснить, но я поместил реализацию конструктора производного класса в файл CPP, а не в определение класса, и ошибка исчезла ...
спасибо всем :)

2 голосов
/ 09 июля 2011

Компоновщик жалуется, что не может найти конструктор для DerivedClass.Попробуйте явно объявить его, определить его и экспортировать из DLL:

Заголовочный файл для DLL:

class DECLSPEC_TEST BaseClass
{
};

class DECLSPEC_TEST DerivedClass : public BaseClass
{
public:
    DerivedClass();
};

Исходный файл cpp для DLL:

DECLSPEC_TEST DerivedClass::DerivedClass() { }
1 голос
/ 09 июля 2011

Несколько вещей для проверки:

  1. Убедитесь, что вы связываетесь с EXACT .LIB файлом, который вы производите из проекта DLL. Случается, что по ошибке мы строим оба проекта, но файл LIB в целевом проекте устарел.
  2. Убедитесь, что связанные файлы CPP в проекте DLL скомпилированы. Использование атрибута __declspec во всех методах не обязательно, так как вы экспортируете весь класс.
  3. Используя Dependency Walker , убедитесь, что DLL действительно имеет класс и все его методы экспортированы.
  4. Убедитесь, что между обоими .LIB-файлами в обоих проектах нет 64-битного / 32-битного несоответствия
1 голос
/ 09 июля 2011

Когда вы скомпилировали свою DLL, вы также получили файл .lib.Это ваша библиотека импорта.Вам нужно будет ссылаться на него, чтобы подключиться к таким зависимостям времени соединения, как эти.

0 голосов
/ 09 июля 2011

Насколько я понимаю, в вашем DerivedClass вы объявили конструктор не по умолчанию (то есть отличный от DerivedClass::DerivedClass()).

В таких случаях компилятор не будет создавать конструктор по умолчанию длявы, поэтому вы должны определить один, так как кажется, что по какой-то причине вы используете конструктор по умолчанию вашего DerivedClass (возможно, в реализации DerivedClass, не обязательно в коде, который использует DLL).1007 * Нет необходимости объявлять конструктор по умолчанию в интерфейсе DLL, но он должен быть там.

Если вы не хотите иметь конструктор по умолчанию, уловка заключается в следующем:

объявляет конструктор по умолчанию в части private определения DerivedClass.

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

0 голосов
/ 09 июля 2011

Единственная пропущенная здесь вещь, которую я вижу, это точка с запятой ; после объявлений классов. Кроме этого, экспорт должен работать нормально.

Еще одна вещь, которую нужно проверить: вы объявили конструктор в производном классе public?

...