C++做一个真正动态链接的DLL的做法

来源:互联网 发布:上海交通大学网络教育 编辑:程序博客网 时间:2024/04/28 10:36

让动态链真正动态是一件很麻的事情。事上,可以称得上“动态”的函数一共就只有两,即全局函数虚函数。所以我有三做法:

第一做法,于接口,不使用任何,所有出函数都用extern "C"的全局函数。

第二做法就是使用COMCOM做了我篇文章所的几乎所有的事情,除此之外还顺便把线程同步这人的事情也一并解决了。

第三做法,出一个全局函数,让这个函数返回一个的接口,然后让这个接口作工厂建的的接口,所有的接口都是,不允使用new象,也不允上分配象。

这样的接口,其构造函数应该protected的,析构函数是一个virtualpublic函数,构造函数和析构函数的函数体不允=0通的解决法是简单的加上一个不行任何代{}函数体

此外DLL量的问题。我的点是旗帜鲜明地反,更,我反任何DLL中的全局量和静态变量,不管是不是要出的。我所同的正确做法是放到上述所的放到那个唯一的全局函数所返回的接口的实现类的成里面。也就是下面代ServiceEntry_Impl中。

由于DLL是依于文件名的,所以很有可能一个程中存在很多不同的CRT,而且它malloc/freenew/delete不能通用,有一个通的解决方案就是让每一个DLL中的一个都用它自己的CRT来管理内存,C++提供一个手段就是重delete,因上面已经说了,我不允new,接口的构造函数都是protected,所以实际上不用考分配的问题,只需要重delete就行了,但是,了解决出函数的函数名的问题了跨编译器,我出函数必是一个全局函数,所以我们还需要出一个相当于delete功能的全局函数,然后再写一个基个基有一个内的重delete,delete用我们导出的那个全局函数。

不要嫌麻,事上,微自己也没有更好的解决法,微GDI+的所有出函数就都是全局函数,然后又把所有都写了一个inline的包装去用那些全局函数。我们这里只不是包装一个delete而已,的函数我虚函数就不用包装了。

最后,忘了用namespace你可以放心的用短的名而不用担心冲突。

上述些要求的具体代码类这样,代中的#include的都被我省略了:

// 文件中这样做:

namespace myspace

{

extern "C" XXX_API void DllDelete(void*); //
出的C格的delete,他的实现就是简单dll中的CRT这样DLL分配的内存由DLL

class Allocateable //
所有的接口应该派生,不用考菱形承的问题Allocateable并没有真的存在任何数据成

{

public:

operator delete(void* p){DllDelete(p);}

};

class XXX : public Allocateable

{

protected:

XXX(){};

public:

virtual ~XXX(){};

virtual void Foo() = 0;

virtual void Bar() = 0;

};

class ServiceEntry : public Allocateable

{

protected:

ServiceEntry(){};

public:

virtual ~ServiceEntry(){};

virtual XXX* CreateXXX() = 0;

virtual YYY* CreateYYY() = 0;

};

extern "C" XXX_API ServiceEntry* NewServiceEntry(); //
是第二个出函数,用使用所有的功能都得从里入手。

}

//
cpp文件里这样做:

namespace myspace

{

void DllDelete(void*p)

{

::operator delete(p);

}

ServiceEntry* NewServiceEntry();

{

return new ServiceEntry_Impl();

}

}

// 此外你需要写具体的实现应该放到不同的文件中

//
ServiceEntry_Impl,要派生自ServiceEntry实现那些成函数

namespace myspace

{

class ServiceEntry_Impl : public ServiceEntry

{

public:

virtual XXX* CreateXXX()

{

return new XXX_Impl();//
似于ServiceEntry_ImplXXX_Impl也需要派生自XXX,并且你得实现XXX的接口。

}

virtual YYY* CreateYYY()

{

return new YYY_Impl();//
同上

}

};

}

原创粉丝点击