Author:halw

Date:2009-01-05T19:34:30.000000Z


git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@152 abb3cda0-5349-4a8f-a601-0c33ac3a8c38
This commit is contained in:
halw
2009-01-05 19:34:30 +00:00
parent ffc468f138
commit 2fa0e9a0ae
7 changed files with 140 additions and 131 deletions

View File

@@ -24,7 +24,7 @@ end
In practice, however, the Eiffel style rules suggest a better documented version:
<code>
indexing
note
description: "Root for trivial system printing a message"
author: "Elizabeth W. Brown"
@@ -50,7 +50,7 @@ The two versions perform identically; the following comments will cover the more
Note the absence of semicolons and other syntactic clatter or clutter. You may in fact use semicolons to separate instructions and declarations. But the language's syntax is designed to make the semicolon optional (regardless of text layout) and it's best for readability to omit it, except in the special case of successive elements on a single line.
The <code>indexing</code> clause does not affect execution semantics; you may use it to associate documentation with the class, so that browsers and other indexing and retrieval tools can help users in search of reusable components satisfying certain properties. Here we see two indexing entries, labeled <code>description</code> and <code>author</code>.
The <code>note</code> clause does not affect execution semantics; you may use it to associate documentation with the class, so that browsers and other indexing and retrieval tools can help users in search of reusable components satisfying certain properties. Here we see two notes, labeled <code>description</code> and <code>author</code>.
The name of the class is <code>HELLO</code>. Any class may contain "features"; <code>HELLO </code>has just one, called <code>make</code>. The <code>create</code> clause indicates that <code>make</code> is a "creation procedure", that is to say an operation to be executed at class instantiation time. The class could have any number of creation procedures.

View File

@@ -13,7 +13,7 @@ For each interface listed in a type library, the EiffelCOM wizard generates a de
Different languages handle type coercion in different ways. C uses type cast; C++ introduces several type casting mechanisms; Eiffel uses assignment attempt, etc. Every COM interface exposes the <eiffel>QueryInterface</eiffel> function which allows clients to query the COM component for a pointer to another interface. Querying a component for an interface pointer is similar to using an assignment attempt in Eiffel. The Eiffel implementation of the assignment attempt relies on the runtime data. Since changing the Eiffel runtime and the implementation of the assignment attempt was not an option, EiffelCOM introduces a library class [[ref:libraries/com/reference/ecom_queriable_chart|ECOM_QUERIABLE]] , which has the creation routine
<code>
make_from_other (other: ECOM_INTERFACE)</code>
make_from_other (other: ECOM_INTERFACE)</code>
which queries a COM component internally. Every interface proxy class inherits from [[ref:libraries/com/reference/ecom_queriable_chart|ECOM_QUERIABLE]] . The one difference between this mechanism versus using assignment attempt is that upon failure an exception will be raised. An assignment attempt that fails simply returns <code>Void</code>.

View File

@@ -13,55 +13,55 @@ ECOM_EXCEPTION provides support for triggering and catching exceptions. Accordin
The status code is mapped by the EiffelCOM runtime to Eiffel exceptions. To raise COM-specific exceptions, the class ECOM_EXCEPTION provides the feature <eiffel>trigger</eiffel>:
<code>
trigger (code: INTEGER)
-- Raise exception with code `code'.
-- See class ECOM_EXCEPTION_CODES for possible values.
</code>
trigger (code: INTEGER)
-- Raise exception with code `code'.
-- See class ECOM_EXCEPTION_CODES for possible values.
</code>
The class also has several features that help analyzing exceptions and error codes received from the COM runtime.
<code>
hresult: INTEGER
-- Original HRESULT.
require
applicable: is_developer_exception
hresult: INTEGER
-- Original HRESULT.
require
applicable: is_developer_exception
hresult_code: INTEGER
-- Status code.
require
applicable: is_developer_exception
hresult_code: INTEGER
-- Status code.
require
applicable: is_developer_exception
hresult_facility: INTEGER
-- Facility code.
require
applicable: is_developer_exception
hresult_facility: INTEGER
-- Facility code.
require
applicable: is_developer_exception
hresult_message: STRING
-- Error message.
require
applicable: is_developer_exception
</code>
hresult_message: STRING
-- Error message.
require
applicable: is_developer_exception
</code>
Every call to COM should be wrapped into a <code> rescue </code> clause as follows:
<code>
some_feature is
local
retried: BOOLEAN
...
do
if not retried then
-- Call to COM.
end
rescue
if is_developer_exception then
-- Compare `hresult' to some predefined value
-- and handle various cases,
-- or display a dialog box with an error message
-- `hresult_message'.
end
retried := True
retry
end
</code>
some_feature
local
retried: BOOLEAN
...
do
if not retried then
-- Call to COM.
end
rescue
if is_developer_exception then
-- Compare `hresult' to some predefined value
-- and handle various cases,
-- or display a dialog box with an error message
-- `hresult_message'.
end
retried := True
retry
end
</code>
==ECOM_STRUCTURE==
@@ -73,9 +73,9 @@ ECOM_VARIANT is a wrapper of the VARIANT structure. VARIANT is the Visual Basic
This wrapper exposes the feature
<code>
variable_type: INTEGER
-- Variable type. See class ECOM_VAR_TYPE for possible values.
</code>
variable_type: INTEGER
-- Variable type. See class ECOM_VAR_TYPE for possible values.
</code>
which specifies the actual type of the variant. The class has multiple features for typed access and setting of variables.
@@ -83,9 +83,9 @@ which specifies the actual type of the variant. The class has multiple features
<eiffel>ECOM_VARIANT_ACCESS</eiffel> provides the feature:
<code>
missing: ECOM_VARIANT
-- Value representing the default value of a COM optional argument.
-- Equivalent to an omitted VB argument, or C++ vtMissing, or .NET System.Reflection.Missing.
missing: ECOM_VARIANT
-- Value representing the default value of a COM optional argument.
-- Equivalent to an omitted VB argument, or C++ vtMissing, or .NET System.Reflection.Missing.
</code>
Many COM Automation servers have routines that take arguments with default values. This is very common, for example, in Microsoft Office applications such as Excel and Word. In Visual Basic, such arguments are optional and, when omitted, the server uses the default value. In languages that cannot omit arguments, a special VARIANT value representing the omitted argument must be passed. EiffelCOM applications can pass missing for this purpose.
@@ -93,21 +93,22 @@ Many COM Automation servers have routines that take arguments with default value
For example, the following adds a new workbook to Excel. The default argument tells Excel to decide for itself how many worksheets to put in the new workbook:
<code>
class
MY_EXCEL_APPLICATION
MY_EXCEL_APPLICATION
inherit
APPLICATION_PROXY
APPLICATION_PROXY
ECOM_VARIANT_ACCESS
ECOM_VARIANT_ACCESS
feature
add_workbook is
local
workbook: WORKBOOK_PROXY
do
workbook := workbooks.add (missing, 0)
end
add_workbook
local
workbook: WORKBOOK_PROXY
do
workbook := workbooks.add (missing, 0)
end
</code>

View File

@@ -19,7 +19,7 @@ The architecture of the generated code is similar to the one used by the code ge
In the case of an out-of-process server, the component might need a Graphical User Interface. There are two different scenarios in which the component can be activated: either its user launched it explicitly (e.g. by double clicking the executable icon) or it was launched by the COM runtime to satisfy a client request. In some cases it might be required for the component to have a different behavior in these two cases (for example the GUI could only be necessary when the component was launched explicitly by the user but should be hidden when launched by the COM runtime). The generated registration class for an out-of-process server includes the feature:
<code>
main_window: WEL_FRAME_WINDOW</code>
main_window: WEL_FRAME_WINDOW</code>
This feature is a <code>once</code> function that can return the class corresponding to the component window. By default, this window is displayed only if COM does not start the component. When COM loads an out-of-process component, it appends the command line parameter "-embedding" to the executable. The generated registration class looks for this option and if it is part of the process argument list then it sets the default window appearance to hidden. Of course this default implementation may be modified if needed.
@@ -27,38 +27,38 @@ This feature is a <code>once</code> function that can return the class correspon
The COM standard specifies that each COM routine should return a status code to the client. The status code is encoded in a <eiffel>HRESULT</eiffel> value. Such behavior goes against the Command Query Separation Principle in Eiffel. The EiffelCOM generated system should use exceptions instead of returning <eiffel>HRESULT</eiffel> values to the client. By default the EiffelCOM runtime will always return <eiffel>S_OK</eiffel> meaning that the routine succeeded. To notify the client of a problem (e.g. invalid argument value), the EiffelCOM component should raise the corresponding exception from class <eiffel>ECOM_EXCEPTION</eiffel> using the feature <eiffel>trigger</eiffel> from the same class. The EiffelCOM runtime will catch the exception and send the corresponding <eiffel>HRESULT</eiffel> back to the client. Here is what the Eiffel code for a COM component should look like:
<code>
indexing
description: "Eiffel coclass server example"
note
description: "Eiffel coclass server example"
class
ECOM_SERVER_COCLASS_IMP
ECOM_SERVER_COCLASS_IMP
inherit
ECOM_SERVER_COCLASS -- Generated by the wizard
ECOM_SERVER_COCLASS -- Generated by the wizard
ECOM_EXCEPTION
export
{NONE} all
end
ECOM_EXCEPTION
export
{NONE} all
end
feature -- Basic Operations
coclass_feature (an_argument: ARGUMENT_TYPE) is
-- Example of a coclass feature
do
if not is_valid (an_argument) then
trigger (E_invalidargument)
else
-- Normal processing
end
end
coclass_feature (an_argument: ARGUMENT_TYPE)
-- Example of a coclass feature
do
if not is_valid (an_argument) then
trigger (E_invalidargument)
else
-- Normal processing
end
end
feature {NONE} -- Implementation
is_valid (an_argument: ARGUMENT_TYPE): BOOLEAN is
-- Is an_argument a valid argument?
do
-- Test of validity of an_argument
end
is_valid (an_argument: ARGUMENT_TYPE): BOOLEAN
-- Is an_argument a valid argument?
do
-- Test of validity of an_argument
end
end -- class ECOM_SERVER_COCLASS_IMP</code>

View File

@@ -27,63 +27,63 @@ where <eiffel>ISOMETHING_INTERFACE</eiffel> is a generated deferred class corres
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 <eiffel>Void</eiffel> Eiffel objects as well as <code>null</code> 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 <eiffel>True</eiffel>. They can be redefined to implement the correct behavior:
<code>
function (a: INTEGER): MY_STRUCT is
-- Example of a generated Eiffel coclass feature
require
function_user_precondition: function_user_precondition
do
...
ensure
non_void_my_struct: Result /= Void
end</code>
function (a: INTEGER): MY_STRUCT
-- Example of a generated Eiffel coclass feature
require
function_user_precondition: function_user_precondition
do
...
ensure
non_void_my_struct: Result /= Void
end</code>
So the complete class hierarchy for an Eiffel client coclass is the following:
[[Image:client-inheritance]]
[[Image:client-inheritance]]
==Exceptions==
The COM standard requires that any interface function returns a status value (known as a <eiffel>HRESULT</eiffel>). 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 <eiffel>HRESULT</eiffel> corresponding to an error code, the EiffelCOM runtime raises an Eiffel exception that needs to be caught by the client.
[[Image:exception-raising]]
[[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 <code>rescue</code> 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 <eiffel>ECOM_EXCEPTION_CODES</eiffel>, which is inherited from by <eiffel>ECOM_EXCEPTION</eiffel>. The later also inherits from the kernel class <eiffel>EXCEPTIONS</eiffel> 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:
<code>
indexing
description: "Eiffel coclass client example"
note
description: "Eiffel coclass client example"
class
COCLASS_CLIENT
COCLASS_CLIENT
inherit
ECOM_EXCEPTION
export
{NONE} all
end
ECOM_EXCEPTION
export
{NONE} all
end
feature -- Basic Operations
coclass_feature_client is
-- Example of a coclass feature caller
local
retried: BOOLEAN
coclass: EIFFEL_COCLASS_PROXY
do
if not retried then
create coclass.make
coclass.coclass_feature -- Actual call
end
rescue
if hresult = E_notimpl then
-- Process non implemented function error.
retried := True
retry
elseif hresult = E_invalidarg then
-- Process invalid argument error.
retried := True
retry
else
-- Forward exception to caller.
end
end
coclass_feature_client
-- Example of a coclass feature caller
local
retried: BOOLEAN
coclass: EIFFEL_COCLASS_PROXY
do
if not retried then
create coclass.make
coclass.coclass_feature -- Actual call
end
rescue
if hresult = E_notimpl then
-- Process non implemented function error.
retried := True
retry
elseif hresult = E_invalidarg then
-- Process invalid argument error.
retried := True
retry
else
-- Forward exception to caller.
end
end
end -- class COCLASS_CLIENT</code>

View File

@@ -2,22 +2,30 @@
[[Property:weight|1]]
[[Property:uuid|5990eda2-2eac-6a40-8e99-5a0c5e9fc15f]]
1 - Launch the Resource Bench application. This small dialog box will appear for the initialization process:
[[Image:retriev]]
Then you get the main window of Resource Bench:
[[Image:rb]]
[[Image:retriev]]
Then you get the main window of Resource Bench:
[[Image:rb]]
2 - Open a resource file (why not the example.rc file provided with this release of Resource Bench). Let the application parse the file. You will see a dialog box that informs you of the parsings state. <br/>
First, there is the preprocessing of the resource file:
[[Image:prepro]]
Then you have the analysis phase:
[[Image:analyz]]
3 - After these two steps you will see a hierarchical view of the resource file that show you what resource's type are included in the resource file (Below the result of the "example.rc" file).
[[Image:collaps]]
You can expand the tree view to see associated resources for each resource's type.
[[Image:expand]]
At this point you are able to:
* Select some properties for the Eiffel code generation
* Save a project file
@@ -28,8 +36,8 @@ At this point you are able to:
4 - To save a project file, click on the save button of the toolbar or select the save item in the file menu. A standard save dialog box will appear in which you can specify the file name of your project. The file's extension for a Resource Bench project is "*.prb"
5 - To generate Eiffel Code, select the "Generate Eiffel Code..." item in the Build menu, this dialog box will appear to ask you in which directory Resource Bench must save the Eiffel classes:
[[Image:browse]]
[[Image:browse]]
6 - To generate a resource file, select the "Generate Resource file..." item in the Build menu, a standard save dialog box will appear to save the file.

View File

@@ -28,7 +28,7 @@ inherit
active_medium
end
creation
create
make
feature
@@ -73,7 +73,7 @@ inherit
BASIC_ROUTINES
creation
create
make
feature
@@ -114,7 +114,7 @@ class
POLLING_SERVER
creation
create
make
feature
@@ -150,7 +150,7 @@ The client follows the same scheme, reversing the order of read and write operat
class
POLLING_CLIENT
creation
create
make
feature