前言:
关于DLL的说明,这里所使用的DLL,并非是一些功能函数的集合,每次调用一个函数实现相应功能即可。而是封装了一个“小程序对象”,其前身是OCX,我们将OCX封装为一个DLL。
因此,此DLL中会存在某个对象A,生存周期伴随调用它的程序。
可以认为,A便是我们封装的“小程序对象”。DLL所有的接口,实际上都是对应调用A的成员函数。
这里便会存在一个问题,多线程情况下,DLL中的这个对象A,是共用的。而我们希望,每个线程所使用到的A是互不干扰的,它只属于各自的线程。
例如OCX调用DLL,浏览器打开N个页面,调用OCX,是多线程的情况。但DLL不会生成多个副本去对应ocx,它只有一个DLL实例在浏览器进程下运行,此时就会出现我们上面所描述的问题。
因此,此处我们使用的对象是指针类型,每个线程,都会拥有它所对应的A。
实现:
采用面向对象方式,进行类的封装,程序中定义基类BASE,DLL中的类CHILD,继承自BASE。CHILD型指针,便是对象A的类型。
BASE类中提供所有的函数接口。在程序中,创建一个成员变量B,类型是BASE*。
我们在DLL中提供接口,用来NEW 一个CHILD,并将指针返还给程序。返还的指针,即赋给B。
此时,我们在程序中使用DLL,即可直接对B进行操作。因为前面所说,DLL所有的接口,实际上都是对应调用A的成员函数。因此,此处直接操作B,调用B的函数即可。
因为我们每个程序实例,都会调用DLL接口,创建各自的A。所以在多线程情况下,也不会冲突。
代码示例:
基类CMyTestBaseClass
class CMyTestBaseClass: public CObject
{
public:
CMyTestBaseClass();
virtual ~CMyTestBaseClass();
public:
virtual void TestShow() = 0;
};
子类CMyTestClass
class CMyTestClass: public CMyTestBaseClass
{
public:
CMyTestClass();
virtual ~CMyTestClass();
public:
void TestShow();
};
DLL提供接口
LONG __declspec(dllexport)Kcxzt_TestCreate();
LONG Kcxzt_TestCreate()
{
CMyTestClass* p = new CMyTestClass;
return (LONG)p;
}
程序中声明一个变量
CMyTestBaseClass* m_testPtr;
为变量赋值
m_testPtr = (CMyTestBaseClass*)(Kcxzt_TestCreate());
之后就可直接使用m_testPtr来操作DLL。