Экспорт классов C ++ из DLL - PullRequest
1 голос
/ 08 июля 2010

Я наткнулся на эту статью о Code Project, в которой говорится об использовании абстрактного интерфейса в качестве альтернативы экспорту всего класса из DLL C ++, чтобы избежать проблем с искажением имен. В определении интерфейса у автора есть метод Release(), который должен вызываться пользователем для освобождения ресурсов объекта класса после его использования. Для автоматизации вызова этого метода автор также создает std::auto_ptr<T> -подобный класс, который вызывает метод Release() перед удалением объекта.

Мне было интересно, будет ли работать следующий подход:

#include <memory>

#if defined(XYZLIBRARY_EXPORT) // inside DLL
#   define XYZAPI   __declspec(dllexport)
#else // outside DLL
#   define XYZAPI   __declspec(dllimport)
#endif  // XYZLIBRARY_EXPORT

// The abstract interface for Xyz object.
// No extra specifiers required.
struct IXyz
{
    virtual int Foo(int n) = 0;

    //No Release() method, sub-class' destructor does cleanup
    //virtual void Release() = 0;

    virtual ~IXyz() {}
};

// Factory function that creates instances of the Xyz object.
// Private function, do not use directly
extern "C" XYZAPI IXyz* __stdcall GetXyz_();

#define GetXyz()      std::auto_ptr<IXyz>( GetXyz_() )

Конечно, GetXyz() может быть глобальной функцией, определенной в заголовке, вместо #define. Преимущество этого метода состоит в том, что нам не нужно создавать собственную производную auto_ptr, которая вызывает метод Release().

Спасибо за ваши ответы, Ashish.

Ответы [ 3 ]

3 голосов
/ 08 июля 2010

делая это, вы рискуете вызвать delete (в вашем процессе, в деструкторе auto_ptr) для объекта, который не создан с помощью соответствующего вызова new () (что делается внутри функции factory, следовательно, внутри dll).Проблема гарантирована, например, когда ваша dll скомпилирована в режиме выпуска, а вызывающий процесс в режиме отладки.

Метод Release () лучше.

2 голосов
/ 08 июля 2010

Это именно так, как работает COM. Избегайте повторного изобретения этого колеса, если вы уже нацелены на Win32 API. Использование интеллектуальных указателей для хранения указателей интерфейса COM очень распространено в программировании Windows, их деструктор вызывает метод Release (). Взгляните на документы MSDN для _com_ptr_t и CComPtr для идей.

1 голос
/ 09 июля 2010

Ограничение, с которым вы сталкиваетесь, если это публичный API, - это CRT, с которым будут связаны различные модули, и что CRT, который создает объект, также должен быть тем, который удаляет его.

Там будетбыть беспорядком, если вы не выберете правильный CRT. Что-нибудь, разделяющее управление памятью, должно использовать CRT (или другое выделение памяти) в качестве внешней библиотеки - т.е.MSVC: многопоточная DLL (/ MD)

Учитывая это, подклассу даже не нужно достигать своей цели.

...