3D PLM Enterprise Architecture

Middleware Abstraction - Object Modeler

Using Components

Creating components, asking for interface pointers, and managing component life cycle
Use Case

Abstract

This article shows how to create interfaces.


What You Will Learn With This Use Case

This use case is intended to show you how to create interfaces that declare either a type or a behavior that a component [1] can implement [2] and that can be used in client application [3].

[Top]

The CAASysUsingComp Use Case

CAASysUsingComp is a use case of the CAASystem.edu framework that illustrates CATIA System framework capabilities.

[Top]

What Does CAASysUsingComp Do

This use case illustrates the usage of components. They are created using a factory, and accessed and modified using pointers to the interfaces they implement. The use case shows also how to manage their life cycle. This use case uses a circle component that implements a circle type interface named CAAISysCircle, and another interface: CAAISysColorProperties.

[Top]

How to Launch CAASysUsingComp

To launch CAASysUsingComp, you will need to set up the build time environment, then compile CAASysUsingComp along with its prerequisites, set up the run time environment, and then execute the use case [4].

Do not type the module name on the command line, but type CNEXT instead. When CATIA is ready, do the following:

[Top]

Where to Find the CAASysUsingComp Code

The CAASysUsingComp use case is made of several classes located in the CAASysUsingComp.m module of the CAASystem.edu framework:

Windows InstallRootDirectory\CAASystem.edu\CAASysUsingComp.m\
Unix InstallRootDirectory/CAASystem.edu/CAASysUsingComp.m/

where InstallRootDirectory is the directory where the CAA CD-ROM is installed.

[Top]

Step-by-Step

To create an interface such as CAAISysCircle, there are three main steps:

#

Step

1 Instantiating the component
2 Modifying the Component Instance Using the CAAISysCircle Interface
3 Retrieve and use a pointer to the CAAISysColorProperties interface
4 Attempting to retrieve a pointer to an interface that the circle component doesn't implement
5 Manage the component life cycle

[Top]

Instantiting the Component

...
  int ReturnCode = 0;
  CAAISysCircle * piSysCircleOnCircle = NULL; 
  HRESULT rc = ::CATInstantiateComponent("CAASysCircle",  
                                         IID_CAAISysCircle,
                                         (void**)&piSysCircleOnCircle);
  if (FAILED(rc))
    return 1; 
...

The CATInstantiateComponent global function creates an instance of the CAASysCircle component and retrieves a pointer to CAAISysCircle. The parameters are:

CAASysCircle Name of the component to instantiate. It's the name of its main class
IID_CAAISysCircle IID of the interface to which a pointer is requested
piSysCircleOnCircle The pointer retrieved to CAAISysCircle

The CATInstantiateComponent global function calls AddRef for the piSysCircleOnCircle pointer returned. To prevent from memory leak, this pointer will be released when it will be no longer needed.

[Top]

Modifying the Component Instance Using the CAAISysCircle Interface

...
  CATMathPoint Center(-4.f,0.f,0.f);
  rc = piSysCircleOnCircle->SetCenter(Center);
  ... // Process failing rc 

  float Radius = 10.f ;
  rc = piSysCircleOnCircle->SetRadius(Radius);
  ... // Process failing rc

  CATMathVector Normal(1.f,0.f,0.f) ;
  CATMathVector Axis (0.f,1.f,0.f)  ;
  rc = piSysCircleOnCircle->SetPlanar(Normal,Axis);
  ... // Process failing rc
...

The center, radius, and support plane are successively set thanks to the SetCenter, SetRadius, and SetPlanar methods of CAAISysCircle [1].

[Top]

Retrieving and Using a Pointer to CAAISysColorProperties Interface

...
  CAAISysColorProperties *piSysColorPropOnCircle = NULL; 
  rc = piSysCircleOnCircle->QueryInterface(IID_CAAISysColorProperties, 
                                           (void**)&piSysColorPropOnCircle);
  if (SUCCEEDED(rc))
  {
    int red   = 100;
    int green = 100;
    int blue  = 100;
    rc = piSysColorPropOnCircle->SetColor(red, green, blue); 
    ... // Check that the color is correctly set
    piSysColorPropOnCircle->Release();
    piSysColorPropOnCircle = NULL;
  }
  else
    ReturnCode = 1;
...

The pointer to the CAAISysCircle interface on the circle component can be used to retrieve pointers to other interfaces implemented by the component, such as a pointer to CAAISysColorProperties, using the QueryInterface method. The variable used to return the pointer must be created with the CAAISysColorProperties type and initialized to NULL. Always test the returned HRESULT value using the macros SUCCEEDED and FAILED. The SetColor method of CAAISysColorProperties can then be used to set the circle color to green. As soon as the pointer to xx is no longer needed, it is released, and set tu NULL.

[Top]

Attempting to Retrieve a Pointer to an Interface that the Circle Component Doesn't Implement

...
  CAAISysPointProperties * piSysPointPropOnCircle = NULL; 
  rc = piSysCircleOnCircle->QueryInterface(IID_CAAISysPointProperties, 
                                           (void**)&piSysPointPropOnCircle);
  if (SUCCEEDED(rc))
  {
    cout << "The circle component doesn't implement CAAISysPointProperties" << endl;
    cout << "This trace should never be displayed" << endl;
    piSysCircleOnCircle->Release();
    piSysCircleOnCircle = NULL;
  }
  else
  {
     cout << "QueryInterface fails: this trace should always be displayed" << endl; 
  }
...

The pointer to the CAAISysCircle interface on the circle component is used to retrieve a pointer to CAAISysPointProperties. The variable used to return the pointer must be created with the CAAISysPointProperties type and initialized to NULL. But since the circle component doesn't implement this interface, QueryInterface will always fail. Even if  this seems improbable, you may find components that you expect to implement a given interface and that do not. For example, you may get a list of pointers to an interface implemented by a set of components, and ask these pointers for another interface. Some of the components may not implement it, and the calling code falls in the case described above. This is the reason why the returned HRESULT value must be tested using the macros SUCCEEDED and FAILED.

[Top]

Managing the Component Life Cycle

...
  piSysCircleOnCircle->Release();
  piSysCircleOnCircle = NULL;
...

The only pointer that remains at thi spoint  is piSysCircleOnCircle. The other pointers created or retrieved were released as soon as they were no longer needed, and set to NULL to prevent from a fortuitious but illegal usage. To prevent from memory leak, piSysCircleOnCircle is released and set to NULL.

[Top]


In Short

This use case shows how to use a component, that is how to create a component using the CATInstantiateComponent global function and retrieve a pointer to an interface the component implements. Using this interface pointer, the component is initialized, and a pointer to another interface is asked for, and used. Then a pointer to an interface that the component doesn't implement is asked for, to show what to do if this happens. The component life cycle is managed by releasing and setting to NULL the interface pointers as soon as they are no longer needed.

[Top]


References

[1] Creating Components
[2] Creating Interfaces
[3] Object Modeler Component and Implementation Inheritance
[4] Building and Launching a CAA V5 Use Case
[Top]

History

Version: 1 [Mar 2000] Document created
[Top]

Copyright © 2000, Dassault Systèmes. All rights reserved.