使用CMake生成的DLL和奇怪的重复模板的不正确行为(C)
我在
Windows上遇到了CMake生成的DLL文件的一个令人困惑的问题.在我的库中,我使用Curiously Recurring Template Pattern为某些类提供唯一的ID号:
// da/Attribute.h: #ifndef DA_ATTRIBUTE_H #define DA_ATTRIBUTE_H namespace da { typedef unsigned int AttributeId; class AttributeBase { public: virtual AttributeId getTypeId() const=0; protected: /** Static ID counter. Every class that derives da::AttributeBase is assigned an increment of this counter as its type ID number */ static AttributeId sNextId; }; template <class Derived> class Attribute : public AttributeBase { private: static AttributeId msTypeId; public: Attribute() { if (msTypeId == 0) { msTypeId = ++sNextId; } } virtual ~Attribute() { } /** For static contexts */ static AttributeId typeId() { if (msTypeId == 0) { msTypeId = ++sNextId; } return msTypeId; } AttributeId getTypeId() const { return typeId(); } }; template <class Derived> AttributeId Attribute<Derived>::msTypeId = 0; } #endif 问题是,当我将DLL链接到可执行项目时,似乎与不同的ID方法存在一些不一致.例如: // Foo.h struct Foo : public da::Attribute<Foo> { Foo() { } }; … // main.cpp Foo *foo = new Foo; Foo->getTypeId() == 1 // True Foo::typeId() == 1 // Should be true,but isn't. Foo::typeId() == 2 通过GDB运行,在Foo :: getTypeID()中断,我发现“msTypeId”和“Foo :: msTypeId”具有不同的内存地址.我勒个去. 这只发生在DLL中定义Foo时. (仅在Windows 7中,显然 – 我的Debian构建中没有这个问题)如果我在main.cpp中创建派生类,或者如果我只是将库中的所有代码编译成可执行文件,则跳过完全DLL步骤,它没有任何问题. 一切都是使用MSYS和MinGW编译的,在Windows 7 Home Premium上使用GCC 4.7. 这是库的CMakeLists.txt,以防我在那里弄乱了一些东西: cmake_minimum_required(VERSION 2.6) project(foo) add_definitions(-std=c++0x) set(CMAKE_BUILD_TYPE Debug) set(sources Foo.cpp ) add_library(foo SHARED ${sources}) 解决方法
您必须从共享库中导出类型.这是使用
__declspec(dllexport) and __declspec(dllimport) 装饰器完成的.阅读MSDN文档;它相当复杂.
由于在构建库时头文件需要__declspec(dllexport),而在编译使用它的代码时需要__declspec(dllimport),因此通常会定义一个符号,通常称为LIBRARYNAME_EXPORT和#ifdefs,具体取决于是否定义了LIBRARYNAME_EXPORTS. 构建(共享)库时,CMake会自动定义target_EXPORTS.可以通过设置DEFINE_SYMBOL目标属性来覆盖它. Unix选择一个不同的路径,默认情况下导出并导入共享库中的所有符号(静态和显式隐藏的除外).这会导致一点性能损失,因为需要解析更多符号,但它更容易使用(从静态切换到共享库不需要更改)并且更加灵活(即可以覆盖共享库中的符号,你无法在Windows中做到). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |