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

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

Chapter 16. Type Codes

16.1 Chapter Overview

This chapter explains the internals of type codes, which are used to carry runtime descriptions of types. Section 16.3 presents the IDL interface for the TypeCode pseudo-object and shows how a type code encodes the details of the IDL type it describes. Section 16.4 explains the C++ mapping for type codes and presents the source code for a decoder that can recursively examine how an IDL type is composed from basic types. Section 16.5 discusses issues related to type code comparison and explains what it means for two types to be the same. Section 16.6 shows how the C++ mapping presents type codes for built-in and user-defined types as constants, and Section 16.7 shows how you can preserve aliasing information of values inside an Any. Section

16.8 covers how type codes are constructed dynamically at run time without compiletime knowledge of the actual IDL types involved.

Much of the information in this chapter may be of only peripheral interest unless you are building an application that must deal with IDL types that are unknown at compile time. For such applications, type codes are essential and form the basis of many of CORBA's dynamic aspects. If you have no immediate interest in such dynamic applications, we suggest you skim Section 16.3 and use this chapter as reference material as the need arises.

16.2 Introduction

As we mention in Section 15.2, a type code is a value that describes an IDL type. For example, if we insert a string into an Any value, the Any's type code effectively says, "The value in this Any is of type string." Type codes are important for the dynamic aspects of CORBA, such as type any, the DII, and the DSI. Type codes ensure that type mismatches are detected at run time and so preserve the type safety of CORBA.

Apart from their type-safety aspects, type codes also provide introspection. Given an Any containing a value of unknown type, you can extract the type code from the Any and interrogate it to determine the type of value that is stored in the Any. This introspection capability is essential for programs that require dynamic typing. For example, the OMG Notification Service [26] requires introspection to determine the distribution of events to consumers based on the contents of values of type any.

16.3 The TypeCode Pseudo-Object

Type codes are values that are manipulated via a TypeCode pseudo-interface. Conceptually, a TypeCode value is a pair of values, as shown in Figure 16.1. The TCKind member of a TypeCode is an enumeration that records the kind of type that is

600

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

described by the type code. For example, if the type code describes a structure, the TCKind member has the value tk_struct, and if the type code describes a string, the TCKind member has the value tk_string.

Figure 16.1 Structure of a TypeCode pseudo-object.

The contents of the description of the type code depend on the value of TCKind. For example, if the type code describes a structure, the description contains the name of the structure and the name and type of each member of the structure. If the type code describes a string, the description contains the value of the bound of the string (if any—a value of zero indicates an unbounded string).

Type codes are pseudo-objects that must be manipulated via an IDL interface. An IDL interface is necessary because the internal structure of the description inside a type code is complex and cannot easily be manipulated as a bare, unencapsulated value. The TypeCode interface appears in the CORBA module:

module CORBA {

// ...

enum TCKind {

tk_null, tk_void, tk_short, tk_long, tk_ushort, tk_ulong, tk_float, tk_double, tk_boolean, tk_char, tk_octet, tk_any, tk_TypeCode, tk_Principal, tk_objref, tk_struct, tk_union, tk_enum, tk_string, tk_sequence, tk_array, tk_alias, tk_except, tk_longlong, tk_ulonglong, tk_longdouble, tk_wchar, tk_wstring, tk_fixed

};

 

 

interface TypeCode { // PIDL

 

exception Bounds {};

 

exception BadKind {};

 

// Operations for all kinds of type codes

 

TCKind

kind();

 

boolean

equal(in TypeCode tc);

 

boolean

equivalent(in TypeCode tc); // CORBA 2.3

TypeCode

get_compact_typecode();

// CORBA 2.3

//For tk_objref, tk_struct, tk_union, tk_enum,

//tk_alias, and tk_except

RepositoryId

id() raises(BadKind);

Identifier

name() raises(BadKind);

// For tk_struct, tk_union, tk_enum, and tk_except

unsigned long

member_count() raises(BadKind);

Identifier

member_name(in unsigned long index)

601

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

 

 

raises(BadKind, Bounds);

// For tk_struct, tk_union, and tk_except

TypeCode

 

member_type(in unsigned long index)

 

 

raises(BadKind, Bounds);

// For tk_union

any

member_label(in unsigned long index)

TypeCode

raises(BadKind, Bounds);

 

discriminator_type() raises(BadKind);

long

 

default_index() raises(BadKind);

// For tk_string, tk_sequence, and tk_array

unsigned long

length() raises(BadKind);

// For tk_sequence, tk_array, and tk_alias

TypeCode

 

content_type() raises(BadKind);

// For tk_fixed

unsigned short fixed_digits() raises(BadKind); unsigned short fixed_scale() raises(BadKind); }; // ...

};

This looks a little intimidating, so we discuss these operations with the TCKind values they apply to. (In Section 16.4 we also show examples in C++ of how to use type codes.)

16.3.1 Types and Operations Applicable to All Type Codes

Depending on the actual type described by a type code, different operations can be invoked to access the details of the type. The kind, equal, and equivalent operations apply to all type codes regardless of the type they describe.

kind

The kind operation returns the TCKind value of a type code. The return value describes what kind of type (such as a structure, a union, or a simple type) is described by the type code. The TCKind value also determines which other operations on the type code you can call to extract more details.

equal

The equal operation allows you to compare two type codes for equality. If two type codes describe exactly the same type, equal returns true. In Section 16.5 we return to what it means for two type codes to be exactly equal.

equivalent

602

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

The equivalent operation (added with CORBA 2.3) also compares two type codes for equality, but it ignores aliases. We explain the semantics of type code equivalence in

Section 16.5.

get_compact_typecode

The get_compact_typecode operation (added with CORBA 2.3) returns a type code that has empty strings for type and member names (repository IDs and alias chains are preserved). We discuss its purpose in Section 16.5.6.

TCKind

The TCKind enumeration lists all possible IDL types. For example, a type code with a TCKind of tk_double describes the IDL type double, and a type code with a TCKind of tk_array describes an array. Most of the TCKind values have the obvious meaning, but there are a few values that deserve further explanation.

tk_null

tk_null indicates that a type code does not describe anything. The value is useful mainly to indicate a "not there" condition. For example, if you default-construct an Any value, the Any's type code TCKind is set to tk_null.

tk_void

tk_void indicates the IDL void type. Of course, an IDL value can never have type void, so a type code with tk_void can never appear as part of an any. However, type codes are also used by the Interface Repository, for which tk_void describes operations that do not return values.

tk_any

Because an any can contain another any, there must be a type code that describes type any.

tk_TypeCode

Type codes are themselves values that can be inserted into an any. It follows that there must be a type code that describes a type code.

tk_Principal

This TCKind value was part of the now deprecated BOA specification. For ORBs that provide a POA, it has no use. (The enumerator was left in the specification for reasons of backward compatibility.)

tk_alias

Type codes with a TCKind of tk_alias describe type definitions, such as

typedef string<4> ShortString;

This type code is used by the Interface Repository.

16.3.2 Type Code Parameters

603

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

The description inside a type code varies with the TCKind value. For example, if TCKind is tk_short, the description is empty, because there is nothing else to say about the type. On the other hand, if TCKind is tk_struct, then there are quite a few details in the description, such as the name of the structure and the name and type of each structure member.

If a type code has a description, the description is composed of one or more parameters; each parameter describes a particular aspect of the type code. For example, a type code describing a bounded string has one parameter that provides the value of the bound. Table 16.1 shows which parameters are present in a type code depending on the TCKind value. (Those TCKind values that do not appear in the table have an empty parameter list.)

 

Table 16.1.. Type code parameters (repeating groups are enclosed in {}).

TCKind

 

Parameters

tk_fixed

 

Digits, scale

tk_objref

 

Repository ID, interface name[a]

tk_struct

 

Structure name,[a] { member name,[a] member type code }.,

 

repository ID[a]

tk_union

 

Union name,[a] discriminator type code, { label value, member name,[a]

 

member type code }., repository ID [a]

tk_enum

 

Enum name,[a] { enumerator name [a] }., repository ID[a]

tk_string

 

Bound

tk_wstring

 

Bound

tk_sequence

Element type code, bound

tk_array

 

Element type code, dimension

tk_alias

 

Alias name,[a] aliased type code, repository ID [a]

tk_except

 

Exception name,[a] { member name,[a] member type code }.,

 

repository ID

 

 

 

[a] Optional parameter (empty string if not present).

[a] Optional parameter in CORBA 2.2 and earlier (empty string if not present), mandatory in CORBA 2.3.

Some type codes, such as tk_objref, have a fixed number of parameters. Others, such as tk_struct, have a variable number of parameters depending on the number of structure members. Note that curly braces denote repeating groups of parameters. For example, each structure member is described as a pair of parameters; one parameter provides the member's name, and the other parameter provides the member's type code.

A number of parameters in Table 16.1 are marked as optional (all optional parameters contain string values). For these parameters, the empty string is a legal value. We discuss the ramifications of empty parameters in Section 16.5.

604

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

The sections that follow describe the type code operations for the TCKind values listed in Table 16.1. Depending on the TCKind value, different operations are used to read the parameter values of a type code.

Type Code Parameters for Fixed-Point Types

If a type code has a TCKind value of tk_fixed, the fixed_digits and fixed_scale operations return the digits and scale, respectively, of the fixed-point type.

If you invoke these operations on a type code whose TCKind is not tk_fixed, the ORB raises a BadKind exception. The same behavior applies to all other operations on the TypeCode interface. If you invoke an operation that does not apply for the current TCKind value, the operation raises BadKind.

Type Code Parameters for Object References

If a type code has a TCKind value of tk_objref, the id operation returns the repository ID of the reference (such as "IDL:acme.com/CCS/Controller:1.0"). The name operation returns the unqualified name of the corresponding interface. For example, for our controller interface, the returned name is "Controller" and not

"CCS::Controller".

Type Code Parameters for Structures

The description of a structure consists of a parameter for the structure's name, a parameter for the structure's repository ID, and a pair of parameters for each structure member; each of these pairs provides the name and the type code of the corresponding member.

The structure name and repository ID are returned by the name and id operations. The member_count operation returns the number of members of the structure. For example, consider this structure:

struct BtData {

TempType

requested;

TempType

min_permitted;

TempType

max_permitted;

string

error_msg;

};

 

Here, member_count returns the value 4.

The value returned by member_count allows you to retrieve the details for each member via the member_name and member_type operations. Members are indexed 0 to member_count - 1. Member indexes follow the order of definition in the IDL, so for this example, member_name(0) returns "requested", member_name(1) returns

"min_permitted", and so on.

605

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

The member_type operation returns the type code that describes the corresponding member. For example, member_type(1) returns a type code with a TCKind of tk_alias because the type of the min_permitted member is itself a type definition. Both member_name and member_type raise a TypeCode::Bounds exception if the passed index is larger than member_count - 1. The same behavior applies if these member functions are invoked with an out-of-range index for a union or an exception type code.

Type Code Parameters for Unions

As with structures, you can use the name, id, member_count, member_name, and member_type operations to retrieve the details of each individual union member.

In addition, union type codes provide operations to retrieve the discriminator type, to retrieve the label value for each union member, and to identify the default member (if any) of a union.

The default_index operation returns the index of the default member of a union. If a union does not have a default member, default_index returns -1.

The discriminator_type operation returns the type code that describes the discriminator of the union.

The member_label returns an any value that contains the value of the union case label for the specified member.

Consider the following union:

union MyUnion switch (long) { case 7:

string s_mem; case 89:

char c_mem; default:

double d_mem;

};

Table 16.2 shows the values returned by the various operations (assuming this union is defined at global scope).

For CORBA 2.3 and later versions, members appear in the same order as in the IDL definition, whereas in earlier versions, members can appear in any order. If a union has a default member, member_label returns the default member's label value as an any containing an octet with value zero. (Because octet is not a legal discriminator type, a label containing an octet is used as a dummy value to indicate the default label.) If you pass an out-of-range index to member_label (an index greater than or equal to member_count), the operation raises the TypeCode::Bounds exception.

606

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

Table 16.2.. Type code operation return values for a union of type MyUnion.

Operation

Return Value

name

MyUnion

id

IDL:MyUnion:1.0

member_count

3

member_name(0)

s_mem

member_name(1)

c_mem

member_name(2)

d_mem

member_type(0)

Type code for string

member_type(1)

Type code for char

member_type(2)

Type code for double

default_index

2

discriminator_type

Type code for long

member_label(0)

any containing the long value 7

member_label(1)

any containing the long value 89

member_label(2)

any containing the octet value 0

If a union has multiple case labels for a single member, the member_count operation counts case labels instead of members. Consider the following example:

union Multiple switch (long) { case 3:

case 7:

char c_mem; case 78:

double d_mem;

};

Table 16.3 shows the values returned by the type code operations for this union. Again, we assume that the union is defined at global scope and that the order of member declarations is not necessarily preserved. Even though the union has only two members, member_count returns 3, and both member_name(0) and member_name(1) return the same string: "c_mem".

Table 16.3.. Type code operation return values for a union of type Multiple.

Operation

Return Value

name

Multiple

id

IDL:Multiple:1.0

member_count

3

member_name(0)

c_mem

member_name(1)

c_mem

member_name(2)

d_mem

member_type(0)

Type code for char

member_type(1)

Type code for char

607

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

member_type(2)

Type code for double

default_index

-1

discriminator_type

Type code for long

member_label(0)

any containing the long value 3

member_label(1)

any containing the long value 7

member_label(2)

any containing the long value 78

Type Code Parameters for Enumerations

For type codes describing enumerations, the name and id operations return the name and the repository ID of the enumeration, respectively. The member_count operation returns the number of enumerators, and the member_name operation returns the name of each enumerator. The indexes for enumerators are in the same order as in the IDL definition, so member_name(0) refers to the first enumerator, member_name(1) refers to the second enumerator, and so on. An out-of-range index for member_name raises a TypeCode::Bounds exception.

Type Code Parameters for Strings and Wide Strings

Strings and wide strings have only a single parameter, which specifies the value of the bound (if any). The length operation returns the value of the bound for a type code with a TCKind value of tk_string or tk_wstring. A value of zero indicates that the string or wide string is unbounded.

Type Code Parameters for Sequences

Type codes for sequences have two parameters: one to indicate the element type and one to indicate the bound (if any). The content_type operation returns the type code describing the element type, and the length operation returns the bound of the sequence (zero length indicates that the sequence is unbounded).

Type Code Parameters for Arrays

Type codes for arrays, like type codes for sequences, have two parameters, which indicate the element type and the dimension of the array. The content_type operation returns the type code describing the element type, and the length operation returns the dimension of the array (which is always non-zero).

Type Code Parameters for Aliases

A type code describing an alias (typedef) contains three parameters, which indicate the name of the aliased type, its type code, and its repository ID. The name operation returns the unqualified name of the type, the content_type operation returns the type code of the aliased type, and the id operation returns the repository ID.

608