我一直在DLL项目中使用Boost但是没有导出任何Boost依赖项......只是C-Types和源自DLL Source树本身的东西。
但现在我正在努力使用可锁定的数据模型......我无法将其设计为异常安全,并且不会将导出类型直接导入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 - 接口,并在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隐藏互斥锁类型并使用可锁定的界面)或者我是否朝这个方向走错了?或者在这种情况下哪些更好?也许将整个boost :: mutex PImpl移动到接口?
答案 0 :(得分:0)
是的,在我看来,你走在正确的轨道上。但是你的结构是如此“沉重”,你应该将它作为一个接口使用值的get和set方法而不是值本身。如果你使用工厂模式,一个用于创建对象的函数和一个用于删除的函数可以安全地从你的dll中的接口派生,甚至不暴露令人讨厌的Pimpl * impl。
再看一下,你可以避免暴露互斥锁。例如,如果只应同时设置两个值,则公开
void setValues(double test1,double test2);
在methode中,您可以自己设置互斥锁。或者更经典的Win32方法,如果你不想要一个大的get和set列表: 使用以下任何方法公开结构:
struct DLLTestData
{
double test1;
double test2;
// …and as many as you want
};
并为您的导出添加功能或方法,如
void setTestData(DLLTestData value);
在您的库中,您可以锁定并记忆整个结构。如前所述,我习惯于在大量使用Win32 API时采用第二种方式,但我个人更喜欢使用接口和get / setter的第一种方法,即使它需要更多的努力。