Вот мое золотое правило относительно DLL и C++.
Код внутри библиотеки DLL может быть написан на C++, но из библиотеки DLL должны экспортироваться только функции C. Но у вас могут быть "фабричные" функции, которые возвращают обратно указатели интерфейса С++
Просто становится грязно, пытаясь экспортировать каждый метод каждого класса из DLL. Дело в компонентах и интерфейсах.
Поскольку вы сказали DLL, это подразумевает Windows. COM — это ответ. КОМ твой друг. Создайте COM-DLL, и ваша проблема с подсчетом ссылок в основном решена. Используйте библиотеки шаблонов ATL (CComObjectRootEx и другие), чтобы сделать реализацию действительно простой. Немного сложно экспортировать синглтон класса C++ с помощью COM. Самый простой подход состоит в том, чтобы класс COM "обертывал" синглтон и просто перенаправлял все вызовы методов в реальный экземпляр синглтона.
Теперь, если вы не знакомы с объектной моделью компонентов, кривая обучения может быть немного крутой. (И большинство справочников тратят слишком много времени на внепроцессные COM, прокси/заглушки DLL, автоматизацию, IDispatch - ни один из них не имеет отношения к вашей проблеме).
Теперь, если у вас нет времени на изучение COM, вот примерная схема реализации одноэлементного шаблона DLL без COM.
// singleton.h (consumed by DLL and users of your singleton)
// IMySingleton is an interface class. It only defines pure virtual methods
class IMySingleton
{
public:
virtual int DoSomething()=0;
virtual int DoSomethingElse()=0;
virtual void AddRef()=0;
virtual void Release()=0;
};
// returns back an instance of IMySingleton with the refcount already at "1"
// This function gets exported out of your DLL(either via .def file or __declexport attribute)
HRESULT GetMySingletonInstance(IMySingleton** ppMySingleton);
// -------------------------------------
// singleton.cpp (compiled into your DLL - but is NOT exported out of the DLL)
class CMySingleton : public IMySingleton
{
public:
int m_refcount;
static CMySingleton* s_pInstance;
// returns an adref'd instance of the singleton
static CMySingleton* GetInstance()
{
if (s_pInstance == NULL)
{
s_pInstance = new CMySingleton(); // refcount at 1
}
else
{
s_pInstance->AddRef();
}
return s_pInstance;
}
CMySingleton()
{
m_refcount = 1;
// your initialization code goes here
}
~CMySingleton()
{
// cleanup code
}
int DoSomething()
{
/// your code goes here
return x;
}
int DoSomethingElse()
{
/// your code goes here
return y;
}
void AddRef() {m_refcount++;}
void Release()
{
m_refcount--;
if (m_refcount == 0)
{
s_pInstance = NULL;
delete this;
}
}
};
// exported out of the DLL
HRESULT GetMySingletonInstance(IMySingleton** ppSingleton)
{
*ppSingleton = static_cast<IMySingleton*>(CMySingleton::GetInstance());
}
Вызывающие объекты, которым требуется доступ к службам синглтона, должны вызвать GetMySingletonInstance только один раз. Когда они уходят, они просто освобождают экземпляр синглтона, вызывая Release() для экземпляра указателя, который у них есть.
person
selbie
schedule
21.02.2011