Previous | Table of Contents | Next |
18.2.10.1 Mapping for interface identifiers
Interface identifiers are used in both CORBA and COM to uniquely identify interfaces. These allow the client code to retrieve
information about, or to inquire about, other interfaces of an object.
CORBA identifies interfaces using the RepositoryId. The RepositoryId is a unique identifier for, among other things, an interface.
COM identifies interfaces using a structure similar to the DCE UUID (in fact, identical to a DCE UUID on Win32) known as an
IID. As with CORBA, COM specifies that the textual names of interfaces are only for convenience and need not be globally unique.
The CORBA RepositoryId is mapped, bidirectionally, to the COM IID. The algorithm
for creating the mapping is detailed in Section 17.5.4, “Mapping Interface Identity,? on
page 17-16.
18.2.10.2 Mapping for exception types
The CORBA object model uses the concept of exceptions to report error information. Additional, exception-specification information
may accompany the exception. The exception-specific information is a specialized form of a record. Because it is defined as
a record, the additional information may consist of any of the basic data types or a complex data type constructed from one
or more basic data types. Exceptions are classified into two types: System (Standard) Exceptions and User Exceptions.
COM provides error information to clients only if an operation uses a return result of type HRESULT. A COM HRESULT with a
value of zero indicates success. The HRESULT then can be converted into an SCODE (the SCODE is explicitly specified as being
the same as the HRESULT on Win32 platforms). The SCODE can then be examined to determine whether the call succeeded or failed.
The error or success code, also contained within the SCODE, is composed of a “facility? major code (13 bits on Win32 and 4
bits on Win16) and a 16-bit minor code.
Unlike CORBA, COM provides no standard way to return user-defined exception data to the client. Also, there is no standard
mechanism in COM to specify the completion status of an invocation. In addition, it is not possible to predetermine what set
of errors a COM interface might return based on the definition of the interface as specified in Microsoft IDL, ODL, or in
a type library. Although the set of status codes that can be returned from a COM operation must be fixed when the operation
is defined, there is currently no machine-readable way to discover the set of valid codes.
Since the CORBA exception model is significantly richer than the COM exception model, mapping CORBA exceptions to COM requires
an additional protocol to be defined for COM. However, this protocol does not violate backwards compatibility, nor does it
require any changes to COM. To return the User Exception data to a COM client, an optional parameter is added to the end of
a COM operation signature when mapping CORBA operations, which raise User Exceptions. System exception information is returned
in a standard OLE Error Object.
Mapping for System Exceptions
System exceptions are standard exception types, which are defined by the CORBA specification and are used by the Object Request
Broker (ORB) and object adapters (OA). Standard exceptions may be returned as a result of any operation invocation, regardless
of the interface on which the requested operation was attempted.
There are two aspects to the mapping of System Exceptions. One aspect is generating an appropriate HRESULT for the operation
to return. The other aspect is conveying System Exception information via a standard OLE Error Object.
The following table shows the HRESULT, which must be returned by the COM View when a CORBA System Exception is raised. Each
of the CORBA System Exceptions is assigned a 16-bit numerical ID starting at 0x200 to be used as the code (lower 16 bits)
of the HRESULT. Because these errors are interface-specific, the COM facility code FACILITY_ITF is used as the facility code
in the HRESULT.
Bits 12-13 of the HRESULT contain a bit mask, which indicates the completion status of the CORBA request. The bit value 00
indicates that the operation did not complete, a bit value of 01 indicates that the operation did complete, and a bit value
of 02
indicates that the operation may have completed. Table 18-3 lists the HRESULT
constants and their values.
Table 18-3 Standard Exception to SCODE Mapping
HRESULT Constant | HRESULT Value | ||||
ITF_E_UNKNOWN_NO | 0x40200 | ||||
ITF_E_UNKNOWN_YES | 0x41200 | ||||
ITF_E_UNKNOWN_MAYBE | 0x42200 | ||||
ITF_E_BAD_PARAM_NO | 0x40201 | ||||
ITF_E_BAD_PARAM_YES | 0x41201 | ||||
ITF_E_BAD_PARAM_MAYBE | 0x42201 | ||||
ITF_E_NO_MEMORY_NO | 0x40202 | ||||
ITF_E_NO_MEMORY_YES | 0x41202 | ||||
ITF_E_NO_MEMORY_MAYBE | 0x42202 | ||||
ITF_E_IMP_LIMIT_NO | 0x40203 |
Table 18-3 Standard Exception to SCODE Mapping (Continued) Table 18-3 Standard Exception to SCODE Mapping (Continued) Table
18-3 Standard Exception to SCODE Mapping (Continued)
ITF_E_IMP_LIMIT_YES | 0x41203 | ||||
ITF_E_IMP_LIMIT_MAYBE | 0x42203 | ||||
ITF_E_COMM_FAILURE_NO | 0x40204 | ||||
ITF_E_COMM_FAILURE_YES | 0x41204 | ||||
ITF_E_COMM_FAILURE_MAYBE | 0x42204 | ||||
ITF_E_INV_OBJREF_NO | 0x40205 | ||||
ITF_E_INV_OBJREF_YES | 0x41205 | ||||
ITF_E_INV_OBJREF_MAYBE | 0x42205 | ||||
ITF_E_NO_PERMISSION_NO | 0x40206 | ||||
ITF_E_NO_PERMISSION_YES | 0x41206 | ||||
ITF_E_NO_PERMISSION_MAYBE | 0x42206 | ||||
ITF_E_INTERNAL_NO | 0x40207 | ||||
ITF_E_INTERNAL_YES | 0x41207 | ||||
ITF_E_INTERNAL_MAYBE | 0x42207 | ||||
ITF_E_MARSHAL_NO | 0x40208 | ||||
ITF_E_MARSHAL_YES | 0x41208 | ||||
ITF_E_MARSHAL_MAYBE | 0x42208 | ||||
ITF_E_INITIALIZE_NO | 0x40209 | ||||
ITF_E_INITIALIZE_YES | 0x41209 | ||||
ITF_E_INITIALIZE_MAYBE | 0x42209 | ||||
ITF_E_NO_IMPLEMENT_NO | 0x4020A | ||||
ITF_E_NO_IMPLEMENT_YES | 0x4120A | ||||
ITF_E_NO_IMPLEMENT_MAYBE | 0x4220A | ||||
ITF_E_BAD_TYPECODE_NO | 0x4020B | ||||
ITF_E_BAD_TYPECODE_YES | 0x4120B | ||||
ITF_E_BAD_TYPECODE_MAYBE | 0x4220B | ||||
ITF_E_BAD_OPERATION_NO | 0x4020C | ||||
ITF_E_BAD_OPERATION_YES | 0x4120C | ||||
ITF_E_BAD_OPERATION_MAYBE | 0x4220C |
ITF_E_NO_RESOURCES_NO | 0x4020D | ||||
ITF_E_NO_RESOURCES_YES | 0x4120D | ||||
ITF_E_NO_RESOURCES_MAYBE | 0x4220D | ||||
ITF_E_NO_RESPONSE_NO | 0x4020E | ||||
ITF_E_NO_RESPONSE_YES | 0x4120E | ||||
ITF_E_NO_RESPONSE_MAYBE | 0x4220E | ||||
ITF_E_PERSIST_STORE_NO | 0x4020F | ||||
ITF_E_PERSIST_STORE_YES | 0x4120F | ||||
ITF_E_PERSIST_STORE_MAYBE | 0x4220F | ||||
ITF_E_BAD_INV_ORDER_NO | 0x40210 | ||||
ITF_E_BAD_INV_ORDER_YES | 0x41210 | ||||
ITF_E_BAD_INV_ORDER_MAYBE | 0x42210 | ||||
ITF_E_TRANSIENT_NO | 0x40211 | ||||
ITF_E_TRANSIENT_YES | 0x41211 | ||||
ITF_E_TRANSIENT_MAYBE | 0x42211 | ||||
ITF_E_FREE_MEM_NO | 0x40212 | ||||
ITF_E_FREE_MEM_YES | 0x41212 | ||||
ITF_E_FREE_MEM_MAYBE | 0x42212 | ||||
ITF_E_INV_IDENT_NO | 0x40213 | ||||
ITF_E_INV_IDENT_YES | 0x41213 | ||||
ITF_E_INV_IDENT_MAYBE | 0x42213 | ||||
ITF_E_INV_FLAG_NO | 0x40214 | ||||
ITF_E_INV_FLAG_YES | 0x41214 | ||||
ITF_E_INV_FLAG_MAYBE | 0x42214 | ||||
ITF_E_INTF_REPOS_NO | 0x40215 | ||||
ITF_E_INTF_REPOS_YES | 0x41215 | ||||
ITF_E_INTF_REPOS_MAYBE | 0x42215 | ||||
ITF_E_BAD_CONTEXT_NO | 0x40216 | ||||
ITF_E_BAD_CONTEXT_YES | 0x41216 |
ITF_E_BAD_CONTEXT_MAYBE | 0x42216 | ||||
ITF_E_OBJ_ADAPTER_NO | 0x40217 | ||||
ITF_E_OBJ_ADAPTER_YES | 0x41217 | ||||
ITF_E_OBJ_ADAPTER_MAYBE | 0x42217 | ||||
ITF_E_DATA_CONVERSION_NO | 0x40218 | ||||
ITF_E_DATA_CONVERSION_YES | 0x41218 | ||||
ITF_E_DATA_CONVERSION_MAYBE | 0x42218 | ||||
ITF_E_OBJ_NOT_EXIST_NO | 0X40219 | ||||
ITF_E_OBJ_NOT_EXIST_MAYBE | 0X41219 | ||||
ITF_E_OBJ_NOT_EXIST_YES | 0X42219 | ||||
ITF_E_TRANSACTION_REQUIRED_NO | 0x40220 | ||||
ITF_E_TRANSACTION_REQUIRED_MAYBE | 0x41220 | ||||
ITF_E_TRANSACTION_REQUIRED_YES | 0x42220 | ||||
ITF_E_TRANSACTION_ROLLEDBACK_NO | 0x40221 | ||||
ITF_E_TRANSACTION_ROLLEDBACK_MAYBE | 0x41221 | ||||
ITF_E_TRANSACTION_ROLLEDBACK_YES | 0x42221 | ||||
ITF_E_INVALID_TRANSACTION_NO | 0x40222 | ||||
ITF_E_INVALID_TRANSACTION_MAYBE | 0x41222 | ||||
ITF_E_INVALID_TRANSACTION_YES | 0x42222 |
It is not possible to map a System Exception’s minor code and RepositoryId into the HRESULT. Therefore, OLE Error Objects
may be used to convey these data. Writing the exception information to an OLE Error Object is optional. However, if the Error
Object is used for this purpose, it must be done according to the following specifications.
• The COM View must implement the standard COM interface ISupportErrorInfo such that the View can respond affirmatively to an inquiry from the client as to whether Error Objects are supported by the View Interface.
• The COM View must call SetErrorInfo with a NULL value for the IErrorInfo pointer parameter when the mapped CORBA operation is completed without an exception being raised. Calling SetErrorInfo in this fashion assures that the Error Object on that thread is thoroughly destroyed.
The properties of the OLE Error Object must be set according to Table 18-4.
Table 18-4 Error Object Usage for CORBA System Exceptions
Property | Description | ||||
bstrSource | <interface name>.<operation name> where the interface and operation names are those of the CORBA interface that this Automation View is representing. | ||||
bstrDescription | CORBA System Exception: [<exception repository id>] minor code [<minor code>][<completion status>] where the <exception repository id> and <minor code> are those of the CORBA system exception. <completion status> is “YES,? “NO,? or “MAYBE? based upon the value of the system exception’s CORBA completion status. Spaces and square brackets are literals and must be included in the string. | ||||
bstrHelpFile | Unspecified | ||||
dwHelpContext | Unspecified | ||||
GUID | The IID of the COM View Interface |
A COM View supporting error objects would have code, which approximates the following C++ example.
SetErrorInfo(OL,NULL); // Initialize the thread-local error objecttry {
// Call the CORBA operation}catch(...) {
...
CreateErrorInfo(&pICreateErrorInfo);pICreateErrorInfo->SetSource(...);pICreateErrorInfo->SetDescription(...); pICreateErrorInfo->SetGUID(...);pICreateErrorInfo ->QueryInterface(IID_IErrorInfo,&pIErrorInfo);pICreateErrorInfo->SetErrorInfo(OL,pIErrorInfo);pIErrorInfo->Release();pICreateErrorInfo->Release();
...}
A client to a COM View would access the OLE Error Object with code approximating the following.
// After obtaining a pointer to an interface on// the COM View, the // client does the following one time
pIMyMappedInterface->QueryInterface(IID_ISupportErrorInfo,&pISupportErrorInfo);
hr = pISupportErrorInfo
->InterfaceSupportsError-Info(IID_MyMappedInterface);BOOL bSupportsErrorInfo = (hr == NOERROR ? TRUE : FALSE);...// Call to the COM operation...HRESULT hrOperation = pIMyMappedInterface->...
if (bSupportsErrorInfo){
HRESULT hr = GetErrorInfo(O,&pIErrorInfo);
// S_FALSE means that error data is not available,
NO_ERROR
// means it is
if (hr == NO_ERROR)
{
pIErrorInfo->GetSource(...);
// Has repository id & minor code. hrOperation (above)
// has the completion status encoded into it.
pIErrorInfo->GetDescription(...);
}}
Mapping for User Exception Types
User exceptions are defined by users in OMG IDL and used by the methods in an object server to report operation-specific errors.
The definition of a User Exception is identified in an OMG IDL file with the keyword exception. The body of a User Exception
is described using the syntax for describing a structure in OMG IDL.
When CORBA User Exceptions are mapped into COM, a structure is used to describe various information about the exception —
hereafter called an Exception structure. The structure contains members, which indicate the type of the CORBA exception, the
identifier of the exception definition in a CORBA Interface Repository, and interface pointers to User Exceptions. If an interface
raises a user exception, a structure is constructed whose name is the interface name [fully scoped] followed by “Exceptions.?
For example, if an operation in MyModule::MyInterface raises a user exception, then there will be a structure created named
MyModule_MyInterfaceExceptions.
A template illustrating this naming convention is as follows.
// Microsoft IDL and ODLtypedef enum { NO_EXCEPTION, USER_EXCEPTION} ExceptionType;
typedef struct
{ExceptionType type;LPTSTR repositoryId;I<ModuleName_InterfaceName>UserException
*....piUserException;
} <ModuleName_InterfaceName>Exceptions;
The Exceptions structure is specified as an output parameter, which appears as the last parameter of any operation mapped
from OMG IDL to Microsoft IDL, which raises a User Exception. The Exceptions structure is always passed by indirect reference.
Because of the memory management rules of COM, passing the Exceptions structure as an output parameter by indirect reference
allows the parameter to be treated as optional by the callee1. The following example illustrates this point.
// Microsoft IDL
interface IBANKAccount{HRESULT Withdraw(}; |
|||||
[in] float fAmount, | |||||
[out] float pfNewBalance, | |||||
[out] BANk_AccountExceptions | |||||
** pException); | |||||
The caller can indicate that no exception information should be returned, if an exception occurs, by specifying NULL as the
value for the Exceptions parameter of the operation. If the caller expects to receive exception information, it must pass
the address of a pointer to the memory in which the exception information is to be placed. COM’s memory management rules state
that it is the responsibility of the caller to release this memory when it is no longer required.
If the caller provides a non-NULL value for the Exceptions parameter and the callee is to return exception information, the
callee is responsible for allocating any memory used to hold the exception information being returned. If no exception is
to be returned, the callee need do nothing with the parameter value.
If a CORBA exception is not raised, then S_OK must be returned as the value of the HRESULT to the callee, indicating the operation
succeeded. The value of the HRESULT returned to the callee when a CORBA exception has been raised depends upon the type of
exception being raised and whether an Exception structure was specified by the caller.
1. Vendors that map the MIDL definition directly to C++ should map the exception struct parameter as defaulting to a NULL
pointer.
The following OMG IDL statements show the definition of the format used to represent User Exceptions.
// OMG IDL
module BANK { ... exception InsufFunds { float balance }; exception InvalidAmount { float amount }; ... interface Account
{exception NotAuthorized { };float Deposit( in float Amount )
raises( InvalidAmount );float Withdraw( in float Amount )raises( InvalidAmount, NotAuthorized );};};
and map to the following statements in Microsoft IDL and ODL.
// Microsoft IDL and ODL
struct Bank_InsufFunds{float balance;};
struct Bank_InvalidAmount{float amount;};
struct BANK_Account_NotAuthorized{};
interface IBANK_AccountUserExceptions : IUnknown{HRESULT _get_InsufFunds( [out] BANK_InsufFunds
* exceptionBody );HRESULT _get_InvalidAmount( [out] BANK_InvalidAmount* exceptionBody );
HRESULT _get_NotAuthorized( [out]BANK_Account_NotAuthorized
* exceptionBody );
};
typedef struct{
ExceptionType type;
LPTSTR repositoryId;
IBANK_AccountUserExceptions * piUserException;
} BANK_AccountExceptions;
User exceptions are mapped to a COM interface and a structure that describes the body of information to be returned for the
User Exception. A COM interface is defined for each CORBA interface containing an operation that raises a User Exception.
The name of the interface defined for accessing User Exception information is constructed from the fully scoped name of the
CORBA interface on which the exception is raised. A structure is defined for each User Exception, which contains the body
of information to be returned as part of that exception. The name of the structure follows the naming conventions used to
map CORBA structure definitions.
Each User Exception that can be raised by an operation defined for a CORBA interface is mapped into an operation on the Exception
interface. The name of the operation is constructed by prefixing the name of the exception with the string “_get_?. Each accessor
operation defined takes one output parameter in which to return the body of information defined for the User Exception. The
data type of the output parameter is a structure that is defined for the exception. The operation is defined to return an
HRESULT value.
If a CORBA User Exception is to be raised, the value of the HRESULT returned to the caller is E_FAIL.
If the caller specified a non-NULL value for the Exceptions structure parameter, the callee must allocate the memory to hold
the exception information and fill in the
Exceptions structure as in Table 18-5.
Table 18-5 User Exceptions Structure
Member |
Description |
||||
type | Indicates the type of CORBA exception that is being raised. Must be USER_EXCEPTION. | ||||
repositoryId | Indicates the repository identifier for the exception definition. | ||||
piUserException | Points to an interface with which to obtain information about the User Exception raised. |
When data conversion errors occur while mapping the data types between object models (during a call from a COM client to a
CORBA server), an HRESULT with the code E_DATA_CONVERSION and the facility value FACILITY_NULL is returned to the client.
Mapping User Exceptions: A Special Case
If a CORBA operation raises only one (COM_ERROR or COM_ERROREX)
user exception (defined under Section 18.3.10.2, “Mapping for COM Errors,? on
page 18-44), then the mapped COM operation should not have the additional parameter
for exceptions. This proviso enables a CORBA implementation of a preexisting COM interface to be mapped back to COM without
altering the COM operation’s original signature.
COM_ERROR (and COM_ERROREX) is defined as part of the CORBA to COM mapping. However, this special rule in effect means that
a COM_ERROR raises clause can be added to an operation specifically to indicate that the operation was originally defined
as a COM operation.
18.2.10.3 Mapping for Nested Types
OMG IDL and Microsoft MIDL/ODL do not agree on the scoping level of types declared within interfaces. Microsoft, for example,
considers all types in a MIDL or ODL file to be declared at global scope. OMG IDL considers a type to be scoped within its
enclosing module or interface. This means that to prevent accidental name collisions, types declared within OMG IDL modules
and OMG IDL interfaces must be fully qualified in Microsoft IDL or ODL.
The OMG IDL construct:
Module BANK{
interface ATM {enum type {CHECKS, CASH};Struct DepositRecord {
string account;float amount;type kind;
}; void deposit (in DepositRecord val); };
Must be mapped in Microsoft MIDL as:
[uuid(...), object]interface IBANK ATM : IUnknown {
typedef [v1 enum] enum{BANK ATM CHECKS,BANK ATM CASH} BANK ATM type;
typedef struct {LPSTR account;BANK ATM type kind;
} BANK ATM DepositRecord;HRESULT deposit (in BANK ATM DepositRecord *val);};
and to Microsoft ODL as:
[uuid(...)]library BANK {...[uuid(...), object]
interface IBANK ATM : IUnknown {typedef enum { BANK ATM CHECKS, {BANK ATM CASH} BANK ATM type;
typedef struct {LPSTR struct;float amount;BANK ATM type kind;
} BANK ATM DepositRecord;HRESULT deposit (in BANK ATM DepositRecord *val);};
18.2.10.4 Mapping for Operations
Operations defined for an interface are defined in OMG IDL within interface definitions. The definition of an operation constitutes
the operations signature. An operation signature consists of the operation’s name, parameters (if any), and return value.
Optionally, OMG IDL allows the operation definition to indicate exceptions that can be raised, and the context to be passed
to the object as implicit arguments, both of which are considered part of the operation.
OMG IDL parameter directional attributes in, out, inout map directly to Microsoft IDL and ODL parameter direction attributes
[in], [out], [in,out]. Operation request parameters are represented as the values of in or inout parameters in OMG IDL, and
operation response parameters are represented as the values of inout or out parameters. An operation return result can be
any type that can be defined in OMG IDL, or void if a result is not returned.
The OMG IDL sample (shown below) illustrates the definition of two operations on the Bank interface. The names of the operations
are bolded to make them stand out. Operations can return various types of data as results, including nothing at all. The operation
Bank::Transfer is an example of an operation that does not return a value. The operation Bank::Open Account returns an object
as a result of the operation.
// OMG IDL
#pragma ID::BANK::Bank?IDL:BANK/Bank:1,2? interface Bank { Account OpenAccount( in float StartingBalance,
in AccountTypes Account(Type);
void Transfer( in Account Account1, in Account Account2, in float Account) raises(InSufFunds);
};
The operations defined in the preceding OMG IDL code are mapped to the following lines of Microsoft IDL code:
// Microsoft IDL[ object, uuid(682d22fb-78ac-0000-0c03-4d0000000000), pointer_default(unique) ]
interface IBANK Teller: IUnknown
{HRESULTHRESULT}; |
|||||
OpenAccount( | |||||
[in] | float | StartingBalance, | |||
[in] | BANK_AccountTypes AccountType, | ||||
[out] IBANK_Account | ** ppiNewAccount ); | ||||
Transfer( | |||||
[in] IBANK_Account * Account1, | |||||
[in] IBANK_Account * Account2, | |||||
[in] float Amount, | |||||
[out] BANK_TellerExceptions | |||||
** ppException); | |||||
and to the following statements in Microsoft ODL
// Microsoft ODL[ uuid(682d22fb-78ac-0000-0c03-4d0000000000) odl ]interface IBANK_Teller: IUnknown
{
HRESULT OpenAccount(
[in] float StartingBalance,
[in] BANK_AccountTypes AccountType,
[out, retval] IBANK_Account
** ppiNewAccount ); HRESULT Transfer( [in] IBANK_Account * Account1,[in] IBANK_Account * Account2,[in] float Amount,[out]BANK_TellerExceptions
** ppException); };
The ordering and names of parameters in the Microsoft IDL and ODL mapping is identical to the order in which parameters are
specified in the text of the operation definition in OMG IDL. The COM mapping of all CORBA operations must obey the COM memory
ownership and allocation rules specified.
It is important to note that the signature of the operation as written in OMG IDL is different from the signature of the same
operation in Microsoft IDL or ODL. In particular, the result value returned by an operation defined in OMG IDL will be mapped
as an output argument at the end of the signature when specified in Microsoft IDL or ODL. This allows the signature of the
operation to be natural to the COM developer. When a result value is mapped as an output argument, the result value becomes
an HRESULT. Without an HRESULT return value, there would be no way for COM to signal errors to clients when the client and
server are not collocated. The value of the HRESULT is determined based on a mapping of the CORBA exception, if any, that
was raised.
It is also important to note that if any user’s exception information is defined for the operation, an additional parameter
is added as the last argument of the operation signature. The user exception parameter follows the return value parameter,
if both
exist. See Section 18.2.10.2, “Mapping for exception types,? on page 18-11 for further
details.
18.2.10.5 Mapping for Oneway Operations
OMG IDL allows an operation’s definition to indicate the invocation semantics the communication service must provide for an
operation. This indication is done through the use of an operation attribute. Currently, the only operation attribute defined
by CORBA is the oneway attribute.
The oneway attribute specifies that the invocation semantics are best-effort, which does not guarantee delivery of the request.
Best-effort implies that the operation will be invoked, at most, once. Along with the invocation semantics, the use of the
oneway operation attribute restricts an operation from having output parameters, must have no result value returned, and cannot
raise any user-defined exceptions.
It may seem that the Microsoft IDL maybe operation attribute provides a closer match since the caller of an operation does
not expect any response. However, Microsoft RPC maybe does not guarantee at most once semantics, and therefore is not sufficient.
Because of this, the mapping of an operation defined in OMG IDL with the oneway operation attribute maps the same as an operation
that has no output arguments.
18.2.10.6 Mapping for Attributes
OMG IDL allows the definition of attributes for an interface. Attributes are essentially a short-hand for a pair of accessor
functions to an object’s data; one to retrieve the value and possibly one to set the value of the attribute. The definition
of an attribute must be contained within an interface definition and can indicate whether the value of the attribute can be
modified or just read. In the example OMG IDL next, the attribute Profile is defined for the Customer interface and the read-only
attribute is Balance-defined for the Account interface. The keyword attribute is used by OMG IDL to indicate that the statement
is defining an attribute of an interface.
The definition of attributes in OMG IDL are restricted from raising any user-defined exceptions. Because of this, the implementation
of an attribute’s accessor function is limited to only raising system exceptions. The value of the HRESULT is determined based
on a mapping of the CORBA exception, if any, that was raised.
// OMG IDL
struct CustomerData{CustomerId Id;string Name;string SurName;};
#pragma ID::BANK::Account "IDL:BANK/Account:3.1"
interface Account
{
readonly attribute float Balance;
float Deposit(in float amount) raises(InvalidAmount);
float Withdrawal(in float amount) raises(InsufFunds, InvalidAmount);
float Close( );
};
#pragma ID::BANK::Customer "IDL:BANK/Customer:1.2"
interface Customer
{
attribute CustomerData Profile;
};
When mapping attribute statements in OMG IDL to Microsoft IDL or ODL, the name of the get accessor is the same as the name
of the attribute prefixed with _get_ in Microsoft IDL and contains the operation attribute [propget] in Microsoft ODL. The
name of the put accessor is the same as the name of the attribute prefixed with _put_ in Microsoft IDL and contains the operation
attribute [propput] in Microsoft ODL.
Mapping for Read-Write Attributes
In OMG IDL, attributes are defined as supporting a pair of accessor functions: one to retrieve the value and one to set the
value of the attribute, unless the keyword readonly precedes the attribute keyword. In the preceding example, the attribute
Profile is mapped to the following statements in Microsoft IDL.
// Microsoft IDL[ object, uuid(682d22fb-78ac-0000-0c03-4d0000000000), pointer_default(unique) ]interface ICustomer : IUnknown
{HRESULTHRESULT}; |
|||||
_get_Profile( [out] | CustomerData | * Profile ); | |||
_put_Profile( [in] | CustomerData | * Profile ); | |||
Profile is mapped to these statements in Microsoft ODL.
// Microsoft ODL[ uuid(682d22fb-78ac-0000-0c03-4d0000000000) ]interface IBANK_Customer : IUnknown
{ [propget] HRESULT Profile( [out] BANK_CustomerData * val); [propput] HRESULT Profile( [in] BANK_CustomerData * val); };
Note – The attribute is actually mapped as two different operations in both Microsoft IDL and ODL. The IBANK_Customer::get_profile
operation (in Microsoft IDL) and the [propget] Profile operation ( in Microsoft ODL) are used to retrieve the value of the
attribute. The IBANK_Customer::put_profile operation is used to set the value of the attribute.
Mapping for Read-Only Attributes
In OMG IDL, an attribute preceded by the keyword readonly is interpreted as only supporting a single accessor function used
to retrieve the value of the attribute. In the previous example, the mapping of the attribute Balance is mapped to the following
statements in Microsoft IDL.
// Microsoft IDL[ object, uuid(682d22fb-78ac-0000-0c03-4d0000000000) ]interface IAccount: IUnknown
{ HRESULT _get_Balance([out] float Balance); };
and the following statements in Microsoft ODL.
// Microsoft ODL[ uuid(682d22fb-78ac-0000-0c03-4d0000000000) ]interface IAccount: IUnknown
{ [propget] HRESULT Balance([out] float *val); };
Note that only a single operation was defined since the attribute was defined to be read-only.
18.2.10.7 Indirection Levels for Operation Parameters
• For integral types (such as long, enum, char,...) these are passed by value as [in] parameters and by reference as out parameters.
• string/wstring parameters are passed as LPSTR/LPWSTR as an in parameter and LPSTR*/LPWSTR* as an out parameter.
• composite types (such as unions, structures, exceptions) are passed by reference for both [in] and [out] parameters.
• optional parameters are passed using double indirection (e.g., IntfException ** val).