跨dll中使用单例 不要使用模板

转载 2016年08月31日 16:10:43

C++中模板单例的跨SO(DLL)问题:RTTI,typeid,static,单例

(转载请注明原创于潘多拉盒子)

C++的模板可以帮助我们编写适合不同类型的模板类,给代码的复用性提供了极大的方便。近来写了一个涉及单例的C++模板类,简化下来可以归结为以下的代码:

1
2
3
4
5
6
7
8
9
10
11
template <typename T>
class Singleton
{
public:
    // 此处省去了多线程安全锁
    static T* getInstance()
    {
    static T t;
    return &t;
  }
};

  那么如果希望对某个work horse类,比如叫做Foo,定义一个Singleton,就会很容易啦:

1
Foo* foo = Singleton<Foo>::getInstance();

 注意这里不需要自己释放foo,因为它不是new出来的。

如果代码被编译成“一个”so(dll)或可执行文件,这里的Singleton得到的对象却是是单例的,也就是说,某一种类型得到的对象地址是确定的。

但是,如果同一个类型的单例在不同的so(dll,可执行文件)中使用,那么得到的同一个类型的单例对象,其地址也是不一样的。比如

libfoo.so文件中的如下代码:

1
2
Foo* foo = Singleton<Foo>::getInstance();
std::type_info fooType = typeid(Singleton<Foo>);

  和libbar.so中的另一端代码:

1
2
3
Foo* bar = Singleton<Foo>::getInstance();
 
std::type_info barType = typeid(Singleton<Foo>);

  其中foo和bar的地址是不同的!他们并不是真正的单例。

为什么呢?原因是模板是编译的时候实例化成“真正的类”的,而在两个不同的so编译生成的过程中,编译器进行了两个不同的实例化过程,他们被实例化成了不同的类。也不是完全不同,但有部分是不同的。

比如,对上述两个so,如果去测试两个Singleton类型是否为同一类型(RTTI):

1
if (fooType == barType)

  那么该测试会返回false。但是,如果测试两个类型的名字是否相等:

1
if (strcmp(fooType.name(), barType.name()) == 0)

  该测试则会返回true。

这说明,两个类型虽然type_info不同,但名字却是相同的。

在Google上搜了一下相关的信息,发现这确实是一个难题。因此,用模板来实现单例,是无法跨so的。当然,这里不是真正用模板来实现单例,只是用这个例子来演示模板的RTTI特性。

DLL入门浅析(2)——如何使用DLL

DLL入门浅析(2)——如何使用DLL 上文我简单的介绍了如何建立一个简单DLL,下面再我简单的介绍一下如何使用一个DLL。当一个DLL被生成后,它创建了一个.dll文件和一个.lib文件;这两个...
  • CSDNMicrosoftCSDN
  • CSDNMicrosoftCSDN
  • 2016年03月21日 16:41
  • 903

在DLL间或者DLL与EXE之间传递vector对象或指针的问题

vector 析构 容器 dll接口 exe
  • cbNotes
  • cbNotes
  • 2014年08月14日 11:15
  • 3701

写C# dll供Unity调用

建立一个C#类库工程 项目属性,.net版本改为2.0,因为高版本unity不兼容 把感叹号的引用去掉 如果需要使用到UnityEngine里的东西,则需要添加引用,Un...
  • linxinfa
  • linxinfa
  • 2015年08月05日 13:53
  • 1843

C++调用DLL方法

调用的原理: 调用DLL,首先需要将DLL文件映像到用户进程的地址空间中,然后才能进行函数调用,这个函数和进程内部一般函数的调用方法相同。Windows提供了两种将DLL映像到进程地址空间的方法...
  • lgh1992314
  • lgh1992314
  • 2013年11月16日 16:28
  • 3103

.NET 项目中引用的DLL 版本不一致的问题

最近遇到了一个问题,和下面的描述相类似:   -- A: Specific version assembly reference Apr 23, 2008 07:18 AM|LINK Good mo...
  • tmeteor
  • tmeteor
  • 2013年07月25日 17:33
  • 8033

VB如何调用DLL

Windows动态连接库是包含数据和函数的模块,可以被其它可执行文件(EXE、DLL、OCX 等)调用。动态连接库包含两种函数:输出(exported)函数和内部(internal)函数。输出函数可...
  • u013408061
  • u013408061
  • 2014年04月21日 16:09
  • 2816

vs2010下C++调用DLL以及怎么生成DLL和为什么使用DLL

一、为什么需要dll代码复用是提高软件开发效率的重要途径。一般而言,只要某部分代码具有通用性,就可将它构造成相对独立的功能模块并在之后的项目中重复使用。 比较常见的例子是各种应用程序框架,如ATL、M...
  • bloke_come
  • bloke_come
  • 2017年07月19日 09:58
  • 405

DLL创建及使用方法

初次接触DLL文件的使用,在网上找了许多资料自己动手写了一些代码,多谢网络上许多大神的教程。俗话说眼过千遍不如手过一遍,现在将这些总结一下也算是对自己的一个提高吧。 1.DLL创建方法 1...
  • twtian01
  • twtian01
  • 2014年08月29日 16:27
  • 2481

在Unity中引用Dll的两种方法

Unity3D 能够很方便的集成一些外部插件,以便调用现有的动态链接库。下面会介绍Unity中如何集成Dll的两种方法。 1.   标准引用 这里所使用的语言是C#。 1.1   新建C#类库项...
  • zhaoguanghui2012
  • zhaoguanghui2012
  • 2016年03月16日 21:45
  • 12452

dll传递stl注意

转自:http://www.cnblogs.com/lidabo/archive/2013/09/04/3300327.html STL跨平台调用会出现很多异常,你可以试试. ...
  • z397164725
  • z397164725
  • 2013年09月11日 14:04
  • 2524
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:跨dll中使用单例 不要使用模板
举报原因:
原因补充:

(最多只允许输入30个字)