在前面的例子当中客户(main函数)和组件不但是静态链接在一切的,而且它们在同一个文件中。在完全实现了IUnknown之后,组件和客户之间变成非常松散的关系。那么这里讨论如何将组件放入到动态链接库(DLL)中。不是要把组件变成一个DLL。DLL只是一个组件服务器。在这里是要将组件变成在DLL中实现的接口集。
组件的创建
如何将组件动态链接到客户中。当然这些都是临时性的,后面的知识将进一步分离客户和组件。在客户可以获取某个组件接口指针之前,它必须先将相应的DLL装载到其进程空间中并创建此组件。
从DLL中输出函数
在客户可以获取某个组件接口指针之前,它必须先将相应的DLL装载到其进程空间中并创建次组件。需要在DLL中输出CreateInstance函数以便客户可以调用它。
先将此需要输出的函数用extern "C"进行标记。
//
// Creation function
//
extern " C " IUnknown * CreateInstance()
... {
IUnknown* pI = static_cast<IX*>(new CA) ;
pI->AddRef() ;
return pI ;
}
// Creation function
//
extern " C " IUnknown * CreateInstance()
... {
IUnknown* pI = static_cast<IX*>(new CA) ;
pI->AddRef() ;
return pI ;
}
还需要高手链接程序需要什么输出函数,要建立一个DEF函数。
CMPNT1.DEF
LIBRARY Cmpnt1.dll
DESCRIPTION ' (c)1996-1997 Dale E. Rogerson '
EXPORTS
CreateInstance @ 1 PRIVATE
LIBRARY Cmpnt1.dll
DESCRIPTION ' (c)1996-1997 Dale E. Rogerson '
EXPORTS
CreateInstance @ 1 PRIVATE
这样就完成了从DLL中输出函数的工作。
DLL装载和调用函数
Create.h和Create.cpp实现了函数CallCreateInstance来装载Dll并调用其中的输出函数CreateInstance()。
//
// Create.h
//
IUnknown * CallCreateInstance( char * name) ;
// create.cpp
#include < iostream.h >
#include < unknwn.h > // Declare IUnknown.
#include " Create.h "
typedef IUnknown * ( * CREATEFUNCPTR)() ;
IUnknown * CallCreateInstance( char * name)
... {
// Load dynamic link library into process.
HINSTANCE hComponent = ::LoadLibrary(name) ;
if (hComponent == NULL)
...{
cout << "CallCreateInstance: Error: Cannot load component." << endl ;
return NULL ;
}
// Get address for CreateInstance function.
CREATEFUNCPTR CreateInstance
= (CREATEFUNCPTR)::GetProcAddress(hComponent, "CreateInstance") ;
if (CreateInstance == NULL)
...{
cout << "CallCreateInstance: Error: "
<< "Cannot find CreateInstance function."
<< endl ;
return NULL ;
}
return CreateInstance() ;
}
// Create.h
//
IUnknown * CallCreateInstance( char * name) ;
// create.cpp
#include < iostream.h >
#include < unknwn.h > // Declare IUnknown.
#include " Create.h "
typedef IUnknown * ( * CREATEFUNCPTR)() ;
IUnknown * CallCreateInstance( char * name)
... {
// Load dynamic link library into process.
HINSTANCE hComponent = ::LoadLibrary(name) ;
if (hComponent == NULL)
...{
cout << "CallCreateInstance: Error: Cannot load component." << endl ;
return NULL ;
}
// Get address for CreateInstance function.
CREATEFUNCPTR CreateInstance
= (CREATEFUNCPTR)::GetProcAddress(hComponent, "CreateInstance") ;
if (CreateInstance == NULL)
...{
cout << "CallCreateInstance: Error: "
<< "Cannot find CreateInstance function."
<< endl ;
return NULL ;
}
return CreateInstance() ;
}
LoadLibrary以被装载的DLL的名称作为参数并返回一个指向所装载的DLL的句柄。
Win32的GetProAdress函数可以使用此句柄以及待调用的函数的名称,然后返回一个指向次函数的指针。
完整的例子参见Inside com 第五章