3D PLM Enterprise Architecture |
Middleware Abstraction - Object Modeler |
Creating and Instantiating a ComponentImplementing CATICreateInstance and using CATInstantiateComponent |
Use Case |
AbstractThis article shows how to create and instantiate a CAA V5 component. |
This use case is intended to show you how to create a CAA V5 component that isolates you implementation from client applications and how client application can instantiate it. The component represents an object with two facets, each of them being supported using an interface:
CreateInstance
in a code extension. Client application instantiate the component using the CATInstantiateComponent
global function.[Top]
CAASysComponent is a use case of the CAASystem.edu framework that illustrates the System framework capabilities.
[Top]
This use case shows a template of the code to write to create a basic component and to enable client applications to instantiate it, retrieve a pointer to an interface this component implements, use this pointer to call methods, and navigate among the other possible interfaces the component implements.
This component is made of the CAASysComponent main class, and of the CAAESysCreateInstanceForComponent extension class. CAAESysCreateInstanceForComponent implements the CATICreateInstance interface to enable the component creation. It is also made of the CAAESysMyInterfaceForComponent class that implements the CAAISysMyInterface interface. Other interfaces could be implemented to replace the latter and make a more realistic component, but have uselessly complicated the use case.
A main program instantiates the component and retrieves a pointer to this CAAISysMyInterface interface to show what the client should do.
Note: Extension links are shown as dashed arrows. Other links are shown as usual.
[Top]
You first need to build CAASysComponent. To do this, you will need to set up the build time environment, then compile the four CAASysComponent*.m modules along with their prerequisites as described in [5]. Launch CAASysComponentCreate itself.
[Top]
The CAASysComponent.m use case is made of four 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:
The first two modules are described in this article. The two others are not described. Refer to their source code.
[Top]
To create a component such as CAASysComponent, there are nine main steps:
# | Step | Where |
---|---|---|
1 | Create the CAASysComponent component main class header file | CAASysComponent.m\LocalInterfaces\CAASysComponent.h |
2 | Create the CAASysComponent component main class source file | CAASysComponent.m\src\CAASysComponent.cpp |
3 | Create the CAAESysCreateInstanceForComponent extension class header file | CAASysComponent.m\LocaInterfaces\CAAESysCreateInstanceForComponent.h |
4 | Create the CAAESysCreateInstanceForComponent extension class source file | CAASysComponent.m\src\CAAESysCreateInstanceForComponent.cpp |
5 | Update the interface dictionary | CAASystem.edu.dico file in CNext\code\dictionary |
6 | Instantiate and use the component | CAASysComponent.m\src\CAASysMain.cpp |
[Top]
#include "CATBaseUnknown.h" //Needed to derive from CATBaseUnknown class CAASysComponent : public CATBaseUnknown { // Used in conjunction with CATImplementClass in the .cpp file CATDeclareClass; public: CAASysComponent(); virtual ~CAASysComponent(); private: // Copy constructor, not implemented // Set as private to prevent from compiler automatic creation as public. CAASysComponent(const CAASysComponent &iObjectToCopy); // Assignment operator, not implemented // Set as private to prevent from compiler automatic creation as public. CAASysComponent & operator = (const CAASysComponent &iObjectToCopy); }; |
The CAASysComponent class C++-derives from CATBaseUnknown.
The CATDeclareClass
macro declares that the class CAASysComponent
belongs to a component. Note that the copy constructor is set as private. The
class has a constructor and a destructor only.
[Top]
#include "CAASysComponent.h" //C++ standard library #include "iostream.h" //------------------------------------------------------------------------------------ // To declare that the class is a component main class CATImplementClass(CAASysComponent, Implementation, CATBaseUnknown, CATNull); //------------------------------------------------------------------------------------ CAASysComponent::CAASysComponent() { cout << "CAASysComponent::CAASysComponent" << endl; } CAASysComponent::~CAASysComponent() { cout << "CAASysComponent::~CAASysComponent" << endl; } |
The CATImplementClass
macro declares that the CAASysComponent
class is a component main class thanks the Implementation
keyword,
and OM-derives [6] from CATBaseUnknown. Any
component main class declared as an Implementation
must C++-derive
and OM-derive from the same class, that must either be CATBaseUnknown or
another component main class. The component main class doesn't implement any
interface, but it could.
[Top]
#include "CATBaseUnknown.h" //Needed to derive from CATBaseUnknown class CAAESysCreateInstanceForComponent : public CATBaseUnknown { // Used in conjunction with CATImplementClass in the .cpp file CATDeclareClass; public: CAAESysCreateInstanceForComponent(); virtual ~CAAESysCreateInstanceForComponent(); // CATICreateInstance // ------------------- virtual HRESULT __stdcall CreateInstance(void **oppv); private: // Copy constructor, not implemented // Set as private to prevent from compiler automatic creation as public. CAAESysCreateInstanceForComponent(const CAAESysCreateInstanceForComponent &iObjectToCopy); // Assignment operator, not implemented // Set as private to prevent from compiler automatic creation as public. CAAESysCreateInstanceForComponent & operator = (const CAAESysCreateInstanceForComponent &iObjectToCopy); }; |
The CAAESysCreateInstanceForComponent extension class derives from CATBaseUnknown.
The CATDeclareClass
macro declares that the class CAAESysCreateInstanceForComponent
belongs to a component. The class has a constructor and a destructor, and
declares the CreateInstance
method which is the only method of the CATICreateInstance
interface. Note that the copy constructor and the assignment operator are set as
private. This is very important for extensions. Since extensions must never be
directly instantiated by client applications, this prevents the compiler from
creating the copy constructor and the assignment operator as public without you
know. They are not implemented in the source file.
[Top]
//Local Framework #include "CAAESysCreateInstanceForComponent.h" //C++ standard library #include "iostream.h" // The class to create #include "CAASysComponent.h" // System Framework #include <CATErrorDef.h> //----------------------------------------------------------------------------------- // To create the TIE object #include "TIE_CATICreateInstance.h" TIE_CATICreateInstance(CAAESysCreateInstanceForComponent); // To declare that the class is a Code extension of CAASysComponent // CATImplementClass(CAAESysCreateInstanceForComponent, CodeExtension, CATBaseUnknown, CAASysComponent); // // To declare that CAAESysCreateInstanceForComponent implements CATICreateInstance, insert // the following line in the interface dictionary: // // CAASysComponent CATICreateInstance libCAASysComponentImpl // //------------------------------------------------------------------------------------ CAAESysCreateInstanceForComponent::CAAESysCreateInstanceForComponent() { cout << "CAAESysCreateInstanceForComponent::CAAESysCreateInstanceForComponent" << endl; } //------------------------------------------------------------------------------------ CAAESysCreateInstanceForComponent::~CAAESysCreateInstanceForComponent() { cout << "CAAESysCreateInstanceForComponent::~CAAESysCreateInstanceForComponent" << endl; } //------------------------------------------------------------------------------------ HRESULT __stdcall CAAESysCreateInstanceForComponent::CreateInstance(void ** oppv) { CAASysComponent * pt = new CAASysComponent(); if (NULL == pt) return(E_OUTOFMEMORY); *oppv = (void *)pt; return(S_OK); } |
The CAAESysCreateInstanceForComponent class states that it implements
the CATICreatInstance interface thanks to the TIE_CATICreateInsatnce
macro. This extension class is dedicated to this component, and the CATImplementClass
macro declares that the CAAESysCreateInstanceForComponent class is
code extension class, thanks to the CodeExtension
keyword, and that
it extends the component whose main class is CAASysComponent. The
third parameter must always be set to CATBaseUnknown, makes no sense, and
is unused for extensions. The CreateInstance
method instantiates
the CAASysComponent component main class. This method is called by
the CATInstantiateComponent
global function that is used by client
applications to instantiate the component [4].
[Top]
... CAASysComponent CATICreateInstance libCAASysComponentImpl ... |
The interface dictionary declares that the CAASysComponent component implements the CAATICreateInstance interface and that the code to load into memory to use these interfaces is located in the libCAASysComponentImpl.m shared library or DLL. Note that the component main class name is used to refer to the component in the interface dictionary, and never the extension class names. Note also that the shared library or DLL to associate with the component/interface pair is the one that contains the code created by the call to the TIE macro (This is generally the same library than the one that contains the interface implementation code, since the TIE macro is usually included in the extension class source file.) This is because when a client asks a component for an interface pointer, the TIE class is instantiated first, and it either retrieves the existing instance of the appropriate extension class, or otherwise instantiates it.
Top]
// System Framework #include "CATErrorDef.h" // For the FAILED macro #include "CATInstantiateComponent.h" // For the global function to create the component #include "CAAISysMyInterface.h" // an interface implemented by the component // C++ standard library #include <iostream.h> // To display traces int main() { cout << "The CAASysComponentCreate Sample begins ....."<< endl; // ------------------------------------------------------------------------------- // Creates the component and retrieves a CAAISysMyInterface interface pointer // ------------------------------------------------------------------------------- CAAISysMyInterface * piSysMyInterfaceOnComponent = NULL; HRESULT rc = ::CATInstantiateComponent( "CAASysComponent", IID_CAAISysMyInterface, (void**)&piSysMyInterfaceOnComponent); if ( FAILED (rc) ) { cout << " Problem in the component Creation"<< endl; return 1 ; } //----------------------------------------------------------------------- //The component is created, and we can use the returned interface pointer //----------------------------------------------------------------------- piSysMyInterfaceOnComponent->Print(); //----------------------------- // Pointer no any longer needed //----------------------------- piSysMyInterfaceOnComponent->Release(); piSysMyInterfaceOnComponent = NULL; cout << endl << "The CAASysComponentCreate Sample is finished."<< endl << endl ; return 0 ; } |
The CAASysComponent component is instantiated using the CATInstantiateComponent
global function to which the following parameters should be passed:
CAASysComponent |
The component identifier that is also the component main class name |
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. CATInstantiateComponent
and the implemented interfaces isolates these 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. The main class
declares the component inheritance and must C++-derive and OM-derive from CATBaseUnknown
or from another component main class. The extension class that implement the CAATICreateInstance
interface must C++-derive from CATBaseUnknown, while OM-inheritance makes
no sense for it. The interface dictionary declares the correspondence between
the component, the interfaces it implements, and the shared library or DLL to
load for each interface. CATInstantiateComponent
is used to
instantiate the component and returns a pointer to the interface requested by
the client application.
[Top]
Version: 1 [May 2002] | Document created |
[Top] |
Copyright © 1994-2002, Dassault Systèmes. All rights reserved.