Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Advanced CORBA Programming wit C++ - M. Henning, S. Vinoski.pdf
Скачиваний:
65
Добавлен:
24.05.2014
Размер:
5 Mб
Скачать

IT-SC book: Advanced CORBA® Programming with C++

interface Thermometer {

typedef string<16> ModelType;

};

interface Hygrometer {

typedef string<32> ModelType;

};

interface HygroTherm : Thermometer, Hygrometer { attribute ModelType model; // Error, 16 or 32 chars?

};

This is illegal because it is no longer clear whether HygroTherm::ModelType has 16 or 32 characters. You can easily get around this problem by using a qualified name:

interface Thermometer {

typedef string<16> ModelType;

};

interface Hygrometer {

typedef string<32> ModelType;

};

interface HygroTherm : Thermometer, Hygrometer {

attribute Thermometer::ModelType model;

// Fine, 16 chars

};

 

4.18 Names and Scoping

IDL's rules for names and name scope resolution are similar to those used by C++ but add a few restrictions to avoid awkward constructs in a number of language mappings. We present these rules here mainly for completeness. If you write clean IDL that uses different identifiers for different things, you will never be in doubt as to which particular definition of an identifier is in scope.

4.18.1 Naming Scopes

Each of the following IDL constructs establishes its own naming scope: Modules

Interfaces

Structures Unions Exceptions

Operation definitions

Identifiers need be unique only within their own scope, so the following IDL is legal:

module CCS {

TempType;

 

typedef short

// MAX_TEMP is a short

const TempType

MAX_TEMP = 99;

interface Thermostat {

// OK

typedef long

TempType;

TempType

temperature();

// Returns long

CCS::TempType nominal_temp();

// Returns short

110

IT-SC book: Advanced CORBA® Programming with C++

};

};

Even though it is legal, you should obviously avoid such reuse of identifiers because it is highly confusing.

4.18.2 Case Sensitivity

Within a naming scope, identifiers must be consistently capitalized:

module CCS {

TempType;

 

typedef short

// Error

const temptype

MAX_TEMP = 99;

};

 

 

The preceding specification does not compile because after an identifier is introduced into a scope, the identifier must be capitalized consistently. Identifiers that differ only in case within the same scope are illegal:

module CCS {

TempType;

 

typedef short

// Error

typedef double

temptype;

};

 

 

After TempType is introduced into a scope, all other capitalizations are "used up." Within different naming scopes, different capitalizations are legal (but confusing):

module CCS {

 

 

typedef short TempType;

 

interface Thermometer {

// OK

typedef long

temptype;

temptype

temperature();

// Returns long

CCS::TempType

nominal_temp();

// Returns short

TempType

max_temp();

// Error

};

 

 

};

 

 

The definition of max_temp does not compile because the name resolution rules ignore the case of an identifier during name lookup. The TempType return type of max_temp first resolves to Thermometer::temptype and then generates an error because the compiler detects that TempType and temptype are used within the same scope.

On the other hand, the definition of nominal_temp compiles OK because the return type CCS::TempType uses a qualified name, and the capitalization of the qualified name agrees with the capitalization at the point of definition.

111

IT-SC book: Advanced CORBA® Programming with C++

4.18.3 Names in Nested Scopes

A name in a nested scope cannot be the same as a name in its immediately enclosing scope. For example:

module CCS { // ...

module CCS { // Error // ...

};

};

Similarly, an interface cannot define a name that is the same as the name of the interface:

interface SomeName {

typedef long SomeName; // Error

};

4.18.4 Name Lookup Rules

The IDL compiler resolves names by successively searching enclosing scopes. For example:

module CCS

{

 

typedef short TempType;

 

// ...

 

 

module Sensors {

// Ugly, but legal

typedef long TempType;

interface Thermometer {

// Returns a long

};

TempType temperature();

 

 

};

module Controllers { // ...

module TemperatureControllers { interface Thermostat {

TempType get_nominal_temp(); // Returns a short

};

};

};

};

In this example, the temperature operation returns a long value because as the compiler searches through the enclosing scopes, the closest definition of the name TempType appears inside module Sensors. The definition of CCS::TempType is hidden inside interface Thermometer by Sensors::TempType.

112

IT-SC book: Advanced CORBA® Programming with C++

On the other hand, the get_nominal_temp operation returns a short value because searching outward through its enclosing scopes, the compiler finds the CCS::TempType definition.

In the presence of inheritance, the compiler searches base interfaces first and then searches the enclosing scopes from the point of lookup. The enclosing scope of base interfaces is never searched during name lookup:

module Sensors {

TempType;

 

typedef short

 

typedef string

AssetType;

 

interface Thermometer {

 

typedef long TempType;

// Returns a long

TempType

temperature();

AssetType

asset_num();

// Returns a string

};

 

 

};

 

 

module Controllers {

TempType;

 

typedef double

 

interface Thermostat : Sensors::Thermometer {

TempType

nominal_temp();

// Returns a long

AssetType

my_asset_num();

// Error

};

 

 

};

 

 

In this example, nominal_temp returns a long instead of a double because base interfaces are searched before the enclosing scope. In other words, inside interface

Thermostat, Sensors::Thermometer::TempType hides Controllers::TempType.

The definition of my_asset_num fails because AssetType is not defined at this point. Even though interface Thermometer is a base interface and uses AssetType, interface Thermometer does not define AssetType. When the compiler looks at the definition of my_asset_num, it does not consider Sensors::AssetType because the enclosing scope of base interfaces is never searched.

4.19 Repository Identifiers and pragma Directives

CORBA provides an Interface Repository that allows run-time access to IDL definitions. The IDL compiler assigns a repository ID to every type in a specification. This repository ID provides a unique identifier for each IDL type and is used as a key into the Interface Repository, where the corresponding type definition is stored.

Repository identifiers can have one of three possible formats, indicated by their ID field: IDL format (default):

IDL:acme.com/CCS/TempType:1.0

113

IT-SC book: Advanced CORBA® Programming with C++

DCE UUID format:

DCE:700dc518-0110-11ce-ac8f-0800090b5d3e:1

LOCAL format:

LOCAL:my personal favorite type name identifier

By default, the IDL compiler generates repository IDs in IDL format.

The DCE format permits DCE universally unique identifiers (UUIDs) [29] to be used as repository identifiers. This is useful, for example, for CORBA-to-DCE protocol translation. The final digit following the colon is a minor version number.

The LOCAL format is completely unconstrained and permits any sequence of characters following the LOCAL: prefix. This format is useful for local interface repositories that do not need to conform to any convention. For example, you could use the LOCAL format to add repository identifiers that link into your revision control system.

4.19.1 The IDL Repository ID Format

The following specification illustrates how the default repository identifiers (in IDL format) are generated:

module CCS {

typedef short TempType; interface Thermometer {

readonly attribute TempType temperature;

};

interface Thermostat : Thermometer {

void

set_nominal_temp(in TempType t);

};

 

};

 

The generated repository identifiers for this specification are as follows:

IDL:CCS:1.0

IDL:CCS/Temptype:1.0

IDL:CCS/Thermometer:1.0

IDL:CCS/Thermometer/temperature:1.0

IDL:CCS/Thermostat:1.0

IDL:CCS/Thermostat/set_nominal_temp:1.0

As you can see, an IDL format repository ID consists of three parts (the IDL prefix, a scoped type name, and a version number). The scoped type name is formed by traversing

114

IT-SC book: Advanced CORBA® Programming with C++

the IDL definition from the outermost to the innermost scope, concatenating the identifiers for each scope with a slash.

4.19.2 The prefix Pragma

IDL repository identifiers provide unique names for every IDL type. However, the mechanism is not perfect; there is always the niggling question, "What if someone else also has created a module called CCS?" Of course, you can make a name clash highly unlikely by choosing a longer name. For example, if you work at the famous Acme Corporation, you could call the module Acme_Corporation_CCS. However, this is not pretty, and it generates very long identifier names for some language mappings. Alternatively, you could nest the CCS module inside another module called Acme_Corporation. This technique works, but it means that all the company's IDL definitions end up in a single module, and that creates administrative problems.

The IDL prefix pragma alleviates the problem by permitting you to add a unique prefix to a repository ID:

#pragma prefix "acme.com" module CCS {

// ...

};

This definition prepends the prefix acme.com to every repository ID:

IDL:acme.com/CCS:1.0

IDL:acme.com/CCS/Temptype:1.0

IDL:acme.com/CCS/Thermometer:1.0

IDL:acme.com/CCS/Thermometer/temperature:1.0

IDL:acme.com/CCS/Thermostat:1.0

IDL:acme.com/CCS/Thermostat/set_nominal_temp:1.0

The obvious question is, how does this help? After all, by adding another prefix at the front, we have simply pushed the problem further away and not solved it. The answer is twofold.

By using a distinct prefix, such as a trademark or a registered Internet domain name, you can make a name clash extremely unlikely.

The prefix for repository identifiers does not affect the generated code. Even though every repository ID has the acme.com prefix, the API generated from the IDL still looks exactly as if no prefix had been specified. Thus, you avoid ending up with ugly identifiers such as Acme_Corporation_CCS::Thermometer in the generated code.

A prefix pragma stays in effect either until it is changed explicitly or until the scope containing the pragma closes (at which point the previous prefix takes effect again). Note

115

IT-SC book: Advanced CORBA® Programming with C++

that an IDL source file is a scope for the purposes of #pragma prefix processing. This means that if you include a file in an IDL definition, any prefix in the included file does not affect the definitions following the #include directive.

It is a good idea to establish a unique prefix for your projects and to use it consistently. This practice ensures that other developers will not clash with your IDL (possibly months or years after it is deployed).

All specifications published by the OMG carry the prefix omg.org.

4.19.3 The version Pragma

IDL also supports a version pragma. It applies only to repository IDs in IDL format. For example:

#pragma prefix "acme.com" module CCS {

typedef short TempType; #pragma version TempType 1.8

// ...

};

This definition assigns version 1.8 to the repository ID for TempType, so the repository ID becomes IDL:acme.com/CCS/TempType:1.8.

The version identifier is a historical relic and is ignored by the ORB. You should never have any reason to change it from the 1.0 default. The version ID was added to repository IDs to allow an interface versioning mechanism to be added to CORBA in the future. As of this writing, no such versioning mechanism exists, and there are no moves in the OMG to add one. This means that versioning in CORBA is limited to specialization—you can treat a derived interface as a later version of a base interface.

Versioning by specialization works fine, provided that you do not have to change any of the base interface's type definitions. In addition, versioning by specialization requires that the semantics of operations in the base interface must not be changed if they are implemented in the derived interface. In practice, versioning is frequently used to address defects in a base interface instead of only to extend the base interface's functionality. Unfortunately, versioning by specialization is not suitable in this case. If types in the base interface must be changed or if the semantics of a base interface's operation must be changed, you have no choice except to define a new, unrelated interface.

4.19.4 Controlling Repository ID Formats with the ID Pragma

The ID pragma allows you to specify explicitly the format of the repository identifier for a type. The pragma applies to all three formats. Its use is best shown by example:

#pragma prefix "acme.com"

116