From 7bf7aefa007dc5bd88bc6003ad684f07b8cf6fc3 Mon Sep 17 00:00:00 2001 From: vwheeler Date: Fri, 18 Apr 2014 20:55:01 +0000 Subject: [PATCH] Clarifications, corrections and grammar. Author:vwheeler Date:2014-04-18T20:55:01.000000Z git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@1326 abb3cda0-5349-4a8f-a601-0c33ac3a8c38 --- .../reusing-com-component.wiki | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/eiffelcom-wizard-reference/reusing-com-component.wiki b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/eiffelcom-wizard-reference/reusing-com-component.wiki index f782b2bd..bf407877 100644 --- a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/eiffelcom-wizard-reference/reusing-com-component.wiki +++ b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/eiffelcom-wizard-reference/reusing-com-component.wiki @@ -1,8 +1,8 @@ [[Property:title|Reusing a COM Component]] [[Property:weight|4]] [[Property:uuid|ae910c51-2264-4b65-2567-9dfc1873beca]] -The wizard generates the necessary code to access the existing component. The plumbing is already done so that instantiating an Eiffel class corresponding to one of the component's coclasses automatically calls the right COM initialization APIs. - +When reusing an existing COM component, the wizard generates the necessary code to access it. The plumbing is already done so that instantiating an Eiffel class corresponding to one of the component's coclasses automatically calls the right COM initialization APIs. + ==Using the Generated Code== Calling a feature on an Eiffel class corresponding to one of the component's coclasses forwards the call to the member on the corresponding interface. The data types of the function arguments are either Eiffel types defined in Eiffel data structure libraries, standard data types defined in the EiffelCOM library, or custom data types declared in the COM definition file. For example, from the following IDL line: @@ -13,7 +13,7 @@ The wizard generates the following feature: function (a: INTEGER): MY_STRUCT_RECORD -where MY_STRUCT_RECORD is a generated Eiffel wrapper around the IDL defined structure MyStruct. Structures represent one case of custom data types, interfaces represent another so for the following IDL: +where MY_STRUCT_RECORD is a generated Eiffel wrapper around the IDL defined structure MyStruct. Structures represent one case of custom data types, interfaces represent another. So for the following IDL: HRESULT Function ([in] ISomething * pInterface) @@ -21,11 +21,12 @@ The wizard generates the following Eiffel feature: function (p_interface: ISOMETHING_INTERFACE) -where ISOMETHING_INTERFACE is a generated deferred class corresponding to the ISomething interface. Calling function requires passing an instance of a type that implements ISOMETHING_INTERFACE. The '''stubs''' implementing such interfaces can be found in '''Server\Interfaces_stub'''. In our example the Eiffel class would be named ISOMETHING_INTERFACE_IMPL_STUB. The default implementation of the stub is empty and should be completed to implement the wanted behavior. This is how callbacks can be implemented using EiffelCOM. +where ISOMETHING_INTERFACE is a generated deferred class corresponding to the ISomething interface. Calling function requires passing an instance of a type that implements ISOMETHING_INTERFACE. The '''stubs''' implementing such interfaces can be found in '''Server\Interfaces_stub'''. In our example the Eiffel class would be named ISOMETHING_IMPL_STUB. The default implementation of the stub is empty and should be completed to implement the wanted behavior. This is how callbacks can be implemented using EiffelCOM. + ==Contracts== -All the Eiffel classes corresponding to the component's interfaces are generated in '''Common\Interfaces'''. These deferred classes include one deferred feature per function defined on the interface. They are equipped with automatically generated assertions. However, the wizard cannot generate fully specified contracts since it has no domain specific knowledge. It can only generate contracts that are domain independent. Such contracts, although useful, are not enough to describe entirely the behavior of the component. Generated contracts include checking for Void Eiffel objects as well as null C pointers for wrappers. There might be a need for additional assertions. Invariants and postconditions can be added in an heir of the generated Eiffel coclass proxy. Preconditions, however, cannot be strengthened. A workaround provided by the wizard consists of generating a precondition function for each feature in the interface. The default implementation of these functions always returns True. They can be redefined to implement the correct behavior: +All the Eiffel classes corresponding to the component's interfaces are generated in '''Common\Interfaces'''. These deferred classes include one deferred feature per function defined in the interface. They are equipped with automatically generated assertions. However, the wizard cannot generate fully specified contracts since it has no domain specific knowledge. It can only generate contracts that are domain independent. Such contracts, although useful, are not enough to describe entirely the behavior of the component. Generated contracts include checking for Void Eiffel objects as well as null C pointers for wrappers. There might be a need for additional assertions. Invariants and postconditions can be added in an heir of the generated Eiffel coclass proxy. Preconditions, however, cannot be strengthened. A workaround provided by the wizard consists of generating a precondition function for each feature in the interface. The default implementation of these functions always returns True. They can be redefined to implement the correct behavior: function (a: INTEGER): MY_STRUCT -- Example of a generated Eiffel coclass feature @@ -39,10 +40,14 @@ All the Eiffel classes corresponding to the component's interfaces are generated So the complete class hierarchy for an Eiffel client coclass is the following: [[Image:client-inheritance]] + + ==Exceptions== The COM standard requires that any interface function returns a status value (known as a HRESULT). This means that any function which adheres to the COM standard actually corresponds to a side effect feature which the Eiffel methodology tries to avoid according to the ''Command Query Separation Principle''. The workaround used in EiffelCOM systems consists in mapping these return values to Eiffel exceptions. So if the component returns an HRESULT corresponding to an error code, the EiffelCOM runtime raises an Eiffel exception that needs to be caught by the client. + [[Image:exception-raising]] + As a result, any feature in the client making calls to the Eiffel classes corresponding to the component's coclasses should include a rescue clause. The processing done in this clause might depend on the nature of the exception. All the standard COM exceptions can be found in the library class ECOM_EXCEPTION_CODES, which is inherited from by ECOM_EXCEPTION. The later also inherits from the kernel class EXCEPTIONS and can consequently be used by the coclass client to catch the exceptions. The following code snippet illustrates how a client can process exceptions raised by a call to an Eiffel class representing a component's coclass: @@ -89,6 +94,3 @@ end -- class COCLASS_CLIENT {{seealso|[[How the EiffelCOM Wizard works|How the EiffelCOM Wizard Works]] , [[Generated Files|Generated Files]] , [[Class Hierarchy|Class Hierarchy]] , [[Eiffel Project Processing|Adding a COM Interface to an Eiffel Project]] , [[Building a COM Component|Reusing a COM Component]] , [[Wizards: Command Line Options|Command Line Options]] }} - - -