3D PLM Enterprise Architecture |
Middleware Abstraction - Object Modeler |
Instantiating a Component using its CLSIDImplementing IClassFactory and using CATCreateInstance |
Use Case |
AbstractThis article shows how to instantiate a CAA V5 component using its CLSID. |
This use case is intended to show you how to create the CLSID for your CAA V5 component and how client applications can instantiate your component using its CLSID. The component referred to this use case is the CAASysComponent component mentioned in [1]. This component represents an object with two facets, each of them being supported using an interface:
CATInstantiateComponent
global
function;Creating these interfaces and their implementations is not described here. You can refer to other articles dealing with this topic [2] [3].
Here we will learn how to allow this component to be instantiated by client
applications using the CATCreateInstance
global function.
[Top]
CAASysComponentCreateCLSID is a use case of the CAASystem.edu framework that illustrates the System framework capabilities.
[Top]
This use case shows the steps to follow to create the CLSID of a basic component to enable client applications to instantiate it.
As in use case [1], this component is made of the CAASysComponent main class, of the CAAESysCreateInstanceForComponent and CAAESysMyInterfaceForComponent extension classes.
For our purpose, it is also made of the CAASysComponentFactory class that implements the IClassFactory interface to enable the component creation using its CLSID.
Finally the component's implementation library must define the CATDllGetClassObject
entry point.
The main program instantiates this component, retrieves a pointer to the CAAISysMyInterface interface this component implements and use this pointer to call a method.
[Top]
You first need to build CAASysComponentCreateCLSID. To do this, you will need to set up the build time environment, then compile all the CAASysComponent*.m modules along with their prerequisites as described in [4]. Launch CAASysComponentCreateCLSID itself.
[Top]
The CAASysComponentCreateCLSID use case is made of five modules:
Windows | InstallRootDirectory\CAASystem.edu\CAASysComponent*.m |
Unix | InstallRootDirectory/CAASystem.edu/CAASysComponent*.m |
where InstallRootDirectory
is the directory where the CAA CD-ROM
is installed.
These modules are:
CATICreateInstance
, the class
that implements IClassFactory
, and the implementation of CATDllGetClassObject
CAAISysMyInterface
interface and its TIE, the interface header being located in the
PublicInterfaces directory of the CAASystem.edu frameworkSome parts of these modules are described in [1]. We only deal here with the new code.
[Top]
To create and use the CLSID of the CAASysComponent, there are five main steps:
# | Step | Where |
---|---|---|
1 | Declare and define the CAASysComponent CLSID | PublicInterfaces\CAASysComponentCLSID.h and CAASysComponentCLSID.m\src\CAASysComponentCLSID.cpp |
2 | Implement the IClassFactory interface | CAASysComponent.m\src\CAASysComponentFactory.cpp |
3 | Implement the CATDllGetClassObject function |
CAASysComponent.m\src\CAASysGetClassObject.cpp |
4 | Update the dictionary | CAASystem.edu.dico and CAASystem.edu.clsid files in CNext\code\dictionary |
5 | Instantiate and use the component | CAASysComponentCreateCLSID.m\src\CAASysMain.cpp |
[Top]
// System Framework #include "IUnknown.h" #ifdef _WINDOWS_SOURCE #ifdef __CAASysComponentCLSID #define ExportedByCAASysComponentCLSID __declspec(dllexport) #else #define ExportedByCAASysComponentCLSID __declspec(dllimport) #endif #else #define ExportedByCAASysComponentCLSID #endif extern "C" ExportedByCAASysComponentCLSID const CLSID CLSID_CAASysComponent; |
#include "CAASysComponentCLSID.h" const CLSID CLSID_CAASysComponent = { /* 876db66d-b22b-435a-8c91-607db2d33663 */ 0x876db66d, 0xb22b, 0x435a, {0x8c, 0x91, 0x60, 0x7d, 0xb2, 0xd3, 0x36, 0x63} }; |
The CLSID of a component is nothing more than a GUID that uniquely identify your component. CLSIDs for components are equivalent to IIDs for interfaces.
The CLSID of a component CAASysComponent
is referred to by the
symbol CLSID_CAASysComponent
which is exported by the
CAASysComponentCLSID library.
To be able to use the CLSID of a component, it is sufficient for client applications to include the CLSID declaration header and to link the code with the CLSID library.
[Top]
#include "CATBaseUnknown.h" // Needed to derive from CATBaseUnknown class CAASysComponentFactory : public CATBaseUnknown { // Used in conjunction with CATImplementClass in the .cpp file CATDeclareClass; public: CAASysComponentFactory(); virtual ~CAASysComponentFactory(); virtual HRESULT __stdcall CreateInstance(IUnknown * iUnkOuter, const IID &iIid, void ** oObject); virtual HRESULT __stdcall LockServer(int iLock); private: // Not implemented CAASysComponentFactory(const CAASysComponentFactory &); // Not implemented CAASysComponentFactory & operator = (const CAASysComponentFactory &); }; |
#include "CAASysComponentFactory.h" // This class declaration #include "iostream.h" // For output #include "CATErrorDef.h" #include "CAASysComponent.h" // The component to create // OM Implementation CATImplementClass(CAASysComponentFactory, Implementation, CATBaseUnknown, CATNull); CAASysComponentFactory::CAASysComponentFactory() { cout << "CAASysComponentFactory::CAASysComponentFactory()" << endl; } CAASysComponentFactory::~CAASysComponentFactory() { cout << "CAASysComponentFactory::~CAASysComponentFactory()" << endl; } // To create the TIE object #include "TIE_IClassFactory.h" TIE_IClassFactory( CAASysComponentFactory ); HRESULT __stdcall CAASysComponentFactory::LockServer(int iLock) { return S_OK; } HRESULT __stdcall CAASysComponentFactory::CreateInstance(IUnknown * iUnkOuter, const IID &iIid, void ** oObject) { CAASysComponent * pCAASysComponent = new CAASysComponent(); if(NULL == pCAASysComponent) return E_OUTOFMEMORY; HRESULT hr = pCAASysComponent->QueryInterface(iIid, oObject); pCAASysComponent->Release(); pCAASysComponent = NULL; return hr; } |
The CAASysComponentFactory
class implements the IClassFactory
interface.
As can be seen, the IClassFactory
interface has two methods but
only CreateInstance
is useful for our purpose, which is to
instantiate our component. The actual implementation is very similar to the
implementation of the CreateInstance
method of the CATICreateInstance
interface as described in [1]. The difference here is
that a query interface is immediately done to retrieve a pointer to an interface
implemented by our component.
[Top]
CATDllGetClassObject
function
// System Framework #include "IUnknown.h" #include "CATErrorDef.h" #include "CATCmpGuid.h" // This Framework #include "CAASysComponentFactory.h" // The component factory to create #include "CAASysComponentCLSID.h" // CLSID declaration of the component #ifdef _WINDOWS_SOURCE #define ExportedByCAASysComponentImpl __declspec(dllexport) #else #define ExportedByCAASysComponentImpl #endif extern "C" HRESULT ExportedByCAASysComponentImpl CATDllGetClassObject(const CLSID & rclsid, const IID & riid, void ** ppv) { HRESULT hr = E_NOTIMPL; if (CATCmpGuid(&rclsid, &CLSID_CAASysComponent)) { CAASysComponentFactory * pCAASysComponentFactory = new CAASysComponentFactory(); if(NULL == pCAASysComponentFactory) return E_OUTOFMEMORY; hr = pCAASysComponentFactory->QueryInterface(riid, ppv); pCAASysComponentFactory->Release(); pCAASysComponentFactory = NULL; } return hr; } |
Defining the factory for our component is not enough. For our component to be
actually instantiable by CLSID in client applications, the library where it is
defined must implement the function CATDllGetClassObject
which will
be the real entry point to the component.
What CATDllGetClassObject
is doing ?
Its purpose is just to instantiate the component factory and to return a
pointer to the IClassFactory
interface that the component factory
implements.
Note that a comparison on the CAASysComponent
CLSID is made at
the beginning to ensure we create the right factory for the component.
[Top]
... CAASysComponentFactory IClassFactory libCAASysComponentImpl ... |
The interface dictionary declares that the CAASysComponentFactory class implements the IClassFactory interface and that the code to load into memory to use this interface is located in the libCAASysComponentImpl shared library or DLL.
CAASystem.edu.clsid:
... {876db66d-b22b-435a-8c91-607db2d33663} CAASysComponent CAASysComponentImpl ... |
The component dictionary links together the CLSID, the name of the component CAASysComponent,
and the shared library or DLL where the entry point CATDllGetClassObject
is defined (which is the component implementation library, CAASysComponentImpl).
Note that the prefix lib is omitted in the library name.
Top]
// System Framework #include "CATErrorDef.h" // For the FAILED macro #include "CATCreateInstance.h" // For the global function to create the component by CLSID // This componennt Framework #include "CAAISysMyInterface.h" // An interface implemented by the component #include "CAASysComponentCLSID.h" // For the CLSID of the component // C++ standard library #include |
The CAASysComponent component is instantiated using the CATCreateInstance
global function to which the following parameters should be passed:
CLSID_CAASysComponent |
The component CLSID, that uniquely identifies the component |
NULL |
Must always be NULL |
0 |
Must always be 0 |
IID_CAAISysMyInterface |
The IID of the interface with which the client application wants to handle the component and to which a pointer is asked |
piSysMyInterfaceOnComponent |
The pointer to that interface |
Once the component is instantiated and handled using a pointer to the
requested interface, the client application can go on using the component. No
link is necessary between the client application and the component code. Only
the library defining the component CLSID is needed for linkage purpose
(CAASysComponentCLSID). CATCreateInstance
and the implemented
interfaces isolates the two codes and are used as a contract between them to
ensure that they will go on running as planned, and that modification to the
component's code will not affect the client application and will ensure run time
compatibility.
[Top]
This use case shows how to create a factory for a component by using its
CLSID. The component factory class implements the IClassFactory interface
and the entry point function CATDllGetClassObject
is implemented in
the component library to instantiate the component factory class. The component
dictionary declares the correspondence between the component CLSID, the
component name, and the component implementation library. CATCreateInstance
is used to instantiate the component knowing its CLSID and returns a pointer to
the interface requested by the client application.
[Top]
[1] | Creating and Instantiating a Component |
[2] | Creating Components |
[3] | Creating Interfaces |
[4] | Building and Launching a CAA V5 Use Case |
[Top] |
Version: 1 [May 2003] | Document created |
[Top] |
Copyright © 1994-2003, Dassault Systèmes. All rights reserved.