Я использовал Boost в проекте DLL, но не экспортировал какие-либо зависимости Boost … пока. Просто C-типы и вещи, которые происходят от самого дерева исходного кода DLL.
Но сейчас я борюсь с блокируемой моделью данных … Я не могу создать безопасную исключительную ситуацию и не направлять типы повышения экспорта в интерфейс DLL.
struct DLL_EXPORT DllTestData {
double test1;
double test2;
void lock();
void unlock();
DllTestDataLock getGuard();
boost::mutex;
}
И использовать это:
DllTestData ptr;
ptr->lock();
ptr->test1 = 1.0;
ptr->unlock();
Можно, по крайней мере, спроектировать, возможно, какой-то DllTestData :: Pimpl и скрыть тип мьютекса от Dll. Но если я хочу использовать это так:
DllTestData ptr;
{
auto g = ptr->getGuard();
ptr->test1 = 1.0;
}
При написании этого я начинаю думать о ILockable-Интерфейс и скрыть тип mutex в PImpl или что-то вроде, так что-то вроде этого:
struct ILockable {
void lock() = 0;
void unlock() = 0;
}
struct DLL_EXPORT DllTestData : public struct ILockable {
/// ...
private:
class PImpl;
Pimpl * impl;
}
struct Guard {
Guard( ILockable * ptr ) {
ptr->lock();
}
~Guard() {
ptr->unlock();
}
}
И используйте это так:
DllTestData ptr = fromDll();
{
Guard g(ptr);
ptr->test1 = 1.0;
}
Будет ли это правильный подход (скрыть тип мьютекса с помощью pimpl и работать с Lockable интерфейс) или я иду в неправильном направлении с этим? Или что будет работать лучше в этом сценарии? Может быть, переместить весь boost :: mutex PImpl в интерфейс?
Да, на мой взгляд, вы на правильном пути. Но ваша структура настолько «тяжелая», что вы должны экспортировать ее как интерфейс с методом get и set значений вместо самих значений. Если вы используете фабричный шаблон, одну функцию для создания объекта и одну для удаления, вы можете безопасно получать данные из интерфейса внутри вашей dll, даже не выставляя противный Pimpl * impl.
Глядя на это снова, вы можете вообще не подвергать мьютекс. Например, если только оба значения должны быть установлены одновременно, выставьте
void setValues(double test1,double test2);
внутри метода вы можете установить мьютекс самостоятельно. Или более классический подход Win32, если вы не хотите большого списка получения и установки:
выставить структуру без какого-либо метода, как:
struct DLLTestData
{
double test1;
double test2;
// …and as many as you want
};
и добавить функцию или метод в ваш экспорт, как
void setTestData(DLLTestData value);
внутри вашей библиотеки вы можете заблокировать и запомнить всю структуру. Как было сказано ранее, я привык ко второму способу при интенсивном использовании Win32 API, но лично я предпочитаю первый подход с интерфейсом и get / setter, даже если это требует больше усилий.
Других решений пока нет …