Dim*_*nov 9 c++ dll templates cross-platform shared-libraries
这是我想要做的:
我正在开发支持插件的跨平台IDE(Linux和Windows).我需要使用类似于Eclipse提供的适配器框架来支持可扩展性.有关详细信息,请参阅此处,但基本上我需要以下内容:
设Adaptee和Adapted是已经存在的,而我们是不允许以任何方式改变完全无关的类.我想创建一个AdapterManager有方法的类
template <class Adaptee, class Adapted> Adapted* adapt( Adaptee* object);
Run Code Online (Sandbox Code Playgroud)
这将创建Adapted给定实例的实例Adaptee.如何创建实例取决于必须注册的适配器函数AdapterManager.每个新插件都应该能够为任意类型提供适配器功能.
以下是我对可能解决方案的看法以及为什么它不起作用:
C++ 11的RTTI函数和type_info类提供了一种hash_code()方法,它为程序中的每种类型返回一个唯一的整数.看到这里.因此,AdapterManager可以简单地包含给定Adaptee的哈希码的映射,并且Adapter类返回指向适配器函数的函数指针.这使得adapt()上面的函数的实现变得微不足道:
template <class Adaptee, class Adapted> Adapted* AdapterManager::adapt( Adaptee* object)
{
AdapterMapKey mk( typeid(Adapted).hash_code(), typeid(Adaptee).hash_code());
AdapterFunction af = adapterMap.get(mk);
if (!af) return nullptr;
return (Adapted*) af(object);
}
Run Code Online (Sandbox Code Playgroud)
任何插件都可以通过简单地在地图中插入附加功能来轻松扩展框架.另请注意,任何插件都可以尝试使任何类适应任何其他类,并且如果存在相应的适配器函数,则AdapterManager无论注册者是谁,都会成功.
type_info结构的两个单独实例以及可能不同的hash_code()结果,这将破坏上述机制.从一个插件注册的适配器功能可能并不总是在另一个插件中工作.问题:
更新1:
该项目将Qt框架用于许多方面,包括插件基础结构.Qt真的有助于跨平台开发.如果你知道问题的Qt特定解决方案,那也是受欢迎的.
更新2:
nm的评论让我意识到我只是在理论上知道这个问题,并没有真正测试过它.所以我使用以下定义在Windows和Linux中进行了一些测试:
template <class T>
class TypeIdTest {
public:
virtual ~TypeIdTest() {};
static int data;
};
template <class T> int TypeIdTest<T>::data;
Run Code Online (Sandbox Code Playgroud)
该类在两个不同的共享库/ DLL中实例化,T = int.两个库都在运行时显式加载.这是我发现的:
在Linux中一切正常:
typeid位于同一地址.在Windows中,两个实例是"有些"不同的:
typeid对不同的情况下返回type_info不同的地址对象.然而,这些对象在测试时是相同的==.相应的哈希码也相等.似乎在Windows上使用类型名称建立类型之间的相等 - 这是有道理的.到现在为止还挺好.dynamic_cast向下转换TypeIdTest派生类型的实例.data.这可能会导致很多问题,并且基本上不允许模板类中的静态字段.总的来说,似乎即使在Windows中,事情也没有我想象的那么糟糕,但我仍然不愿意使用这种方法,因为模板实例化仍然使用不同的vtable和静态存储.有谁知道如何避免这个问题?我没有找到任何解决方案.
我认为 Boost Extension 正是解决这个问题领域:
http://boost-extension.redshoelac.com/docs/boost/extension/index.html
(准备将该库提交给 Boost 进行审核)
您尤其会对作者在这篇博文中所写的内容感兴趣:“跨 DLL 边界的资源管理:
RTTI 并不总是按预期跨 DLL 边界运行。查看 type_info 类,看看我是如何处理这个问题的。
我不确定他的解决方案是否真的可靠,但他之前确实有过这个想法。事实上,有一些使用 Boost Extensions 的示例,您可以尝试一下,您可能想使用它。