From 5cc5b8cdea37fa256f9af8df34ffba18246dbead Mon Sep 17 00:00:00 2001 From: halw Date: Thu, 6 Aug 2009 20:07:09 +0000 Subject: [PATCH] Author:halw Date:2009-08-06T20:07:09.000000Z git-svn-id: https://svn.eiffel.com/eiffel-org/trunk@280 abb3cda0-5349-4a8f-a601-0c33ac3a8c38 --- .../com-and-eiffel/access-type.wiki | 29 ++++++++---- .../com-and-eiffel/com-concepts.wiki | 1 - .../com-and-eiffel/com-interfaces.wiki | 1 - .../com-and-eiffel/component-location.wiki | 5 ++- .../com-and-eiffel/deeper-com.wiki | 44 +++++++++++++------ .../eiffelcom-introduction.wiki | 1 - .../eiffelcom-wizard-introduction.wiki | 14 ++++-- 7 files changed, 64 insertions(+), 31 deletions(-) diff --git a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/access-type.wiki b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/access-type.wiki index 042fee3b..77366a0b 100644 --- a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/access-type.wiki +++ b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/access-type.wiki @@ -1,9 +1,14 @@ [[Property:title|Access Type]] [[Property:weight|5]] [[Property:uuid|0d049617-9737-7cc8-810a-9f6f9ca603ec]] -Regardless of its location, a COM components can be accessed either directly through interface's virtual table or through OLE Automation. +Regardless of its location, a COM components can be accessed either through OLE '''Automation''' or '''directly''' through the interface's virtual table. + ==Automation== -Accessing a COM component through Automation means using a well known interface to access to a group of methods and properties. This interface is called IDispatch, and it includes the method invoke that allows to call a method, set or get a property on the Automation server. One advantage of that approach is that the interface has a known virtual table layout. As a result, Windows can include a built-in marshaler for that interface (See [[Deeper into COM|Marshaling]] for information on what a marshaler is). The supported types (known as Automation types) and their Eiffel equivalents are listed in the following table: + +Accessing a COM component through Automation means using a well-known interface to access to a group of methods and properties. This interface is called '''IDispatch''', and it includes the method invoke that allows calling a method, setting or getting a property on the Automation server. + +One advantage of this approach is that the interface has a known virtual table layout. As a result, Windows can include a built-in marshaler for that interface (See [[Deeper into COM]] for information on marshalers). The supported types (known as Automation types) and their Eiffel equivalents are listed in the following table: + {| |- | @@ -204,17 +209,25 @@ ECOM_DECIMAL Decimal value |} -The other advantage is a more dynamic discovery of the methods and properties of a component at runtime. Indeed the IDispatch interface also includes methods to check whether a method or property is available and, in that case, get its identifier. This process is called late binding and allows component to discover at runtime what are other components functionality. -This approach has also a lot of drawbacks: first, late binding is not an efficient way of calling a function on an interface since its identifier must first be requested and then the function called. That's two round trips which can be expensive in a distributed environment. Second, since the marshaler is built-in, it has to know in advance all the possible types that a function can accept to be able to marshal the corresponding data. There are consequently a limitation on the number of types that one can use in signatures of functions on an Automation compatible interface. The set of available types is called Variant and cover most of the standard types. It does not allow however the passing of complex user defined data types. For these reasons Automation is mostly used in scripting environments (where speed is not an important factor) to accomplish simple tasks. + +Another advantage is a more dynamic discovery of the methods and properties of a component at runtime. Indeed the IDispatch interface also includes methods to determine whether or not a method or property is available and, in the case that it is available, get its identifier. This process is called late binding and allows component to discover at runtime the availability of functionality on other components. + +This approach has also a lot of drawbacks. First, late binding is not an efficient way of calling a function on an interface. This is because first its identifier must be requested, and then the function called. That's two round trips which can be expensive in a distributed environment. Second, since the marshaler is built-in, it has to know in advance all the possible types that a function can accept to be able to marshal the corresponding data. Consequently, there is a limitation on the number of types that one can use in signatures of functions on an Automation compatible interface. The set of available types is called '''Variant''' and cover most of the standard types. It does not allow however the passing of complex user defined data types. + +For these reasons Automation is mostly used in scripting environments (where speed is not an important factor) to accomplish simple tasks. ==Direct Access== -Direct interface access is the preferred way to access remote servers where speed becomes a concern and data types are specific to the application. The first interface pointer on the component is obtained through the class object (see [[Coclass|Class Object]] ). Other interfaces on the component are obtained by calling the QueryInterface function. -As information on any interface cannot be accessed dynamically, the description of the interfaces must be provided to tools that need to handle the components such as the EiffelCOM wizard. The official way of describing components and interfaces is through IDL. Once an IDL file has been written to describe a component it can be compiled with MIDL to generate both a type library and the code for the marshaller specific to that interface. + +Direct interface access is the preferred way to access remote servers where speed becomes a concern and data types are specific to the application. The first interface pointer on the component is obtained through the class object (see [[Coclass|Class Object]] ). Other interfaces on the component are obtained by calling the '''QueryInterface''' function. + +Because information on any interface cannot be accessed dynamically, the description of the interfaces must be provided to tools that need to handle the components such as the EiffelCOM wizard. The official way of describing components and interfaces is through Interface Definition Language (IDL). Once an IDL file has been written to describe a component it can be compiled with MIDL (the Microsoft IDL compiler) to generate both a type library and the code for the marshaler specific to that interface. ==EiffelCOM== -The idea in EiffelCOM is the way a component is accessed is implementation detail that the user should not have to deal with. Of course he should be able to choose what kind of access he wants to use but this choice should have no impact on the design of the Eiffel system itself. For that reason, the Eiffel code generated by the wizard follows the same architecture independently of the choice made for interface access and marshalling. The difference lies in the runtime where the actual calls to the components are implemented. + +One idea behind EiffelCOM is that the details of how a component is accessed should be of no concern to an EiffelCOM programmer. Of course the programmer should be able to choose which kind of access he or she wants to use, but this choice should have no impact on the design of the Eiffel system itself. For that reason, the Eiffel code generated by the wizard follows the same architecture independently of the choice made for interface access and marshaling. The differences in access are handled in the runtime where the actual calls to the components are implemented. + + {{seealso|
-[[EiffelCOM Wizard|EiffelCOM wizard]]
[[EiffelCOM Library| EiffelCOM library]]
[[EiffelCOM: Introduction| Introduction]]
[[Generalities|Generalities]]
diff --git a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/com-concepts.wiki b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/com-concepts.wiki index f10bc292..808e0885 100644 --- a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/com-concepts.wiki +++ b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/com-concepts.wiki @@ -4,7 +4,6 @@ [[Property:uuid|9cb19fc1-3d26-5752-6232-ea23f2668c32]] COM is a binary standard that describes how a component can communicate with the outside world. The component communicates through well-defined interfaces. Each interface is a specification of a group of properties and methods. Importantly, the interface does not contain the implementation of the properties and methods, only their specifications (signatures). The actual implementation lies in the [[Coclass|'''coclass''']]. There can be different implementations of a same interface in different coclasses. Finally, each coclass can be instantiated using a class object or class factory. These three notions will be discussed further in the forthcoming paragraphs. {{seealso|
-[[EiffelCOM Wizard|EiffelCOM wizard]]
[[EiffelCOM Library| EiffelCOM library]]
[[EiffelCOM: Introduction| Introduction]]
[[COM Interfaces| COM Interfaces]]
diff --git a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/com-interfaces.wiki b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/com-interfaces.wiki index 2ca22244..e0dd4e4f 100644 --- a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/com-interfaces.wiki +++ b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/com-interfaces.wiki @@ -10,7 +10,6 @@ The COM specification requires that any interface provide access to all interfac The two other functions exposed by '''IUnknown''' are '''AddRef''' and '''Release'''. These functions should be called respectively when a client gets a reference on an interface or when it discards that reference. These two functions define the life-cycle of a component at runtime: each interface tracks clients by keeping a reference on each of them. When there are no client references anymore, the component can be unloaded from memory. You might worry that this business of reference counting will the source of problems such as memory leaks. You would be right, should you choose a low-level language in which to implement your components. Fortunately, you will never have to implement or use these functions in Eiffel: all the processing related to IUnknown is provided by the EiffelCOM runtime. Calls to '''QueryInterface''' are done "behind the scene" and only when needed. The component life-cycle is also taken care of by the EiffelCOM runtime. {{seealso|
-[[EiffelCOM Wizard|EiffelCOM wizard]]
[[EiffelCOM Library| EiffelCOM library]]
[[EiffelCOM: Introduction| Introduction]]
[[Generalities|Generalities]]
diff --git a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/component-location.wiki b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/component-location.wiki index 08c67aa9..9c4c46c8 100644 --- a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/component-location.wiki +++ b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/component-location.wiki @@ -4,7 +4,7 @@
==Types of Components== Certainly you've heard of ActiveX, DirectX, OCX, COM+, ADO+, ASP, and other Microsoft technologies. These are all technologies that use the COM standard. This paragraph will focus on categorizing COM components according to their own properties as well as the context in which they are used. The categorization will define how the EiffelCOM wizard should be used to wrap or create a component. -The first criterion that defines the type of component is its origin: will the component be loaded in the client process or will the component be a remote server for a distributed application? In the former case, the component is compiled as a Dynamic Link Libraries (DLL) while in the latter case it is a standard executable. +The first criterion that defines the type of component is its origin: will the component be loaded in the client process (in-process) or will the component be a remote server for a distributed application (out-of-process)? In the former case, the component is compiled as a Dynamic Link Libraries (DLL) while in the latter case it is a standard executable. ==In-process Components== @@ -12,7 +12,8 @@ Typical instances of DLL components are found in technologies such as OCX, Activ One main difference with out-of-process components (other than the nature of the module, DLL versus executable) is the way in-process components are activated. In the case of out-of-process components, the component will specify COM when it is ready to receive calls from client. In the case of an in-process server the call is coming directly from COM: COM first loads the DLL into the client process and then calls the exported function DllGetClassObject to access the component class object. The other three exported functions of an in-process component are DllRegister to register the component in the Windows registry, DllUnregister to unregister the component from the registry and finally DllCanUnloadNow which gets called by COM whenever it tries to unload the component from memory. These four functions must be accessible from outside the DLL for the in-process component to work properly. ==Out-of-process Components== -These components are standard executable acting as servers that can be accessed locally or over a network. Typically used in a three tier client server architecture, the major difference with in-process servers (other than the module type - executable instead of DLL) is their lifetime. In-process components are typically loaded to achieve a specific task and unloaded just after while out-of-process components are servers supposed to run continuously. The EiffelCOM wizard allows to build clients for such servers in Eiffel. It also provides the ability to create such servers. +These components are standard executable acting as servers that can be accessed locally or over a network. Typically used in a three tier client server architecture, the major difference with in-process servers (other than the module type - executable instead of DLL) is their lifetime. In-process components are typically loaded to achieve a specific task and unloaded just after the task is complete. Out-of-process components are servers, intended to run continuously. The EiffelCOM wizard allows to build clients for such servers in Eiffel. It also provides the ability to create such servers. + {{seealso|
[[EiffelCOM Library| EiffelCOM library]]
diff --git a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/deeper-com.wiki b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/deeper-com.wiki index f8780475..48602657 100644 --- a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/deeper-com.wiki +++ b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/deeper-com.wiki @@ -1,24 +1,40 @@ [[Property:title|Deeper into COM]] [[Property:weight|6]] [[Property:uuid|f28ee911-1b15-260c-a290-540b9531113a]] -The next paragraph gives some details on the COM internals. The understanding of these details are not required to use the EiffelCOM wizard but might help making better decisions when designing new EiffelCOM components. +'''Apartment models''' and '''Marshalling''' are two more interesting areas of COM internals. It is not necessary to understand these details to use the EiffelCOM wizard, but the knowledge could improve decision making when designing new EiffelCOM components. -==Apartments== -The first interesting subject that requires more in-depth cover is the execution context of a component. Components can be run in the same process as the client but can also run in a separate process even on a different machine. -This superficial description only take into accounts processes. What happens if a component uses multithreading to achieve it tasks? In a case of a remote server, this scenario does not seem too esoteric. The problem is that a server does not (and should not) know in advance what its clients will be. It cannot assume that the client will be able to take advantage of its multithreading capabilities. Conversely a multithreaded client should not rely on the server ability to handle concurrent access. +==Apartment models== -The solution chosen in the COM specification is to define an additional execution context called an apartment. When COM loads a component it creates the apartment in which the component will run. Multiple instances of a multithreaded component will leave together in the same apartment since asynchronous calls will be handled correctly and there is no need to add any synchronization layer. On the other hand, single threaded component will be alone in their apartment and any concurrent calls coming from clients will be first synchronized before entering the apartment. These two behaviors define two different kinds of apartments: Multi Threaded Apartments (MTA) and Single Threaded Apartments (STA). -
[[Image:com-2|Apartments]]
Apartments solve the problem of concurrency by removing the necessity of knowing the multithreaded capability of a component and its clients. Multithreaded clients can always make asynchronous calls and depending on whether the component handles concurrent access or not, they will be forwarded or first synchronized. There can be multiple instances of STA running in one process while there will be at most one MTA. -==Marshaling== -At this point you might wonder how calls can "cross" the apartments boundaries. Components from a STA can make calls to components running in a MTA and vice versa. These apartments might be running in different processes or even on different machines. The approach chose in the COM specification is using the proxy and stub patterns. -The idea is to trick the client of an interface by providing an interface proxy in its apartment. The proxy include exactly the same function as the interface itself but their implementation will just forward the call to the actual interface. The client has no idea whether the entity it is dealing with is the actual interface or just a proxy. One of the main interest of that approach is that the client implementation is independent from the location of the component. +The first interesting subject that warrants more in-depth coverage is the execution context of a component. Components can run in the same process as the client, but can also run in a separate process, even on a different machine. But this only takes processes into account. What happens if a component uses multithreading to achieve it tasks? In the case of remote servers, this is a very real possibility. The problem is that a server does not (and should not) know in advance the nature of its clients. It cannot assume that the client will be able to take advantage of its multithreading capabilities. Conversely a multithreaded client should not rely on the server's ability to handle concurrent access. + +The solution chosen in the COM specification is to define an additional execution context called an '''apartment'''. When COM loads a component it creates the apartment in which the component will run. Multiple instances of a multithreaded component will coexist in the same apartment since asynchronous calls will be handled correctly and there is no need to add any synchronization layer. On the other hand, single threaded components will be alone in their apartments and any concurrent calls coming from clients will be first synchronized before entering the apartment. These two behaviors define two different kinds of apartments: '''Multi Threaded Apartments''' (MTA) and '''Single Threaded Apartments''' (STA). + + +[[Image:com-2|Apartments]] + + +Apartments solve the problem of concurrency by removing the necessity of knowing the multithreaded capability of a component and its clients. Multithreaded clients can always make asynchronous calls and depending on whether the component handles concurrent access or not, they will be forwarded directly or synchronized first. There can be multiple instances of a STA running in one process, while there can be at most one MTA. + +==Marshalling== + +COM calls can "cross" apartment boundaries. Components from an STA can make calls to components running in an MTA and vice versa. These apartments might be running in different processes or even on different machines. The approach chosen in the COM specification for cross-apartment calls involves a pattern of '''proxies''' and '''stubs'''. + +The idea is to "trick" the client of an interface by providing an interface proxy in its apartment. The proxy includes exactly the same functions as the interface itself but the implementations will merely forward the call to the actual interface. The clients behavior is the same whether it is dealing the actual interface or just a proxy. A point of interest in this approach is that the client implementation is independent from the location of the component. + +But this is not quite the whole story. The call that goes to a proxy will not be forwarded to the actual interface but to its stub. The stub is the counterpart of the proxy, it represents the client for the interface. The interface's behavior is the same whether it is communicating with the actual client or a stub. Although it is not totally true that the component implementation is independent from the location of the client, the stub pattern still helps keeping code identical for the implementation of the interface themselves. The implementation of a component will still be different whether it is an in-process or out-of-process component, since it will have to be a DLL in one case and a executable in the other. The design of the interfaces might also differ since out-of-process servers will tend to avoid too many round trips. + + +[[Image:com-3|Cross Apartment Calls]] + + +There is one proxy/stub pair per interface. The proxy or the stub is loaded dynamically only when needed. This proxy/stub pair constitute the '''marshaller'''. The reason for having a single name for two different things come from how MIDL generates its code. MIDL will produce files for one DLL in which both the proxy and the stub will be included. This DLL is the marshaller. -Last explanation is not totally accurate: the call will not be forwarded to the actual interface but to its stub. The stub is the counterpart of the proxy, it represents the client for the interface. The interface doesn't know either whether it is communicating with the actual client or a stub. Although it is not totally true that the component implementation is independent from the location of the client, the stub pattern still helps keeping code identical for the implementation of the interface themselves. The implementation of a component will still be different whether it is an in-process or out-of-process component since it will have to be a DLL in one case and a executable in the other. The design of the interfaces might also differ since out-of-process servers will tend to avoid too many round trips. -
[[Image:com-3|Cross Apartment Calls]]
There is one proxy/stub pair per interface. The proxy or the stub is loaded dynamically only when needed. This proxy/stub pair constitute the marshaller. The reason for having a single name for two different things come from how MIDL generates its code. MIDL will produce files for one DLL in which both the proxy and the stub will be included. This DLL is the marshaller.
==Summary== -This brief introduction to the Component Object Model should be enough to get started with the EiffelCOM wizard. It specifies the main characteristics that define the type of a component and that need to be given to the wizard along with the definition file.
-{{seealso| -[[EiffelCOM Wizard|EiffelCOM wizard]]
+ +This brief introduction to the Component Object Model should be enough to get started with the EiffelCOM wizard. It specifies the main characteristics that define the type of a component and that need to be given to the wizard along with the definition file. + + +{{seealso|
[[EiffelCOM Library| EiffelCOM library]]
[[Generalities| Generalities]]
[[Deeper into COM| Deeper into COM]]
diff --git a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/eiffelcom-introduction.wiki b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/eiffelcom-introduction.wiki index 329e666e..0ed12d37 100644 --- a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/eiffelcom-introduction.wiki +++ b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/com-and-eiffel/eiffelcom-introduction.wiki @@ -9,7 +9,6 @@ The advantages of such an approach include an increased reusability (binary reus {{seealso|
-[[EiffelCOM Wizard|EiffelCOM wizard]]
[[EiffelCOM Library| EiffelCOM library]]
[[Generalities| Generalities]]
[[COM Interfaces| COM Interfaces]]
diff --git a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/eiffelcom-wizard-introduction.wiki b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/eiffelcom-wizard-introduction.wiki index 0ca9f27f..316363c1 100644 --- a/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/eiffelcom-wizard-introduction.wiki +++ b/documentation/current/platform-specifics/microsoft-windows/com/eiffelcom-wizard/eiffelcom-wizard-introduction.wiki @@ -1,16 +1,22 @@ [[Property:title|EiffelCOM Wizard Introduction]] [[Property:weight|-14]] [[Property:uuid|b73bc137-55ce-5404-e178-d88565cb6b62]] -The COM standard allows software components written in different languages to communicate with each other. However, building COM compliant applications requires the development of a large amount of code only dedicated to supporting the technology. The EiffelCOM wizard was designed to free Eiffel developers from having to write the plumbing code. +The COM standard allows software components written in different languages to communicate with each other. However, building COM compliant applications requires the development of a large amount of "plumbing" code dedicated to supporting the technology. The EiffelCOM wizard was designed to free Eiffel developers from having to write the plumbing code. -The EiffelCOM wizard is a powerful tool that enables the fast development of COM components in Eiffel and accessing COM components from Eiffel systems. It consists of a series of input fields, which ask about the component's characteristics. The wizard needs the data to produce an Eiffel system skeleton, the code to access or create a component, and the component-specific runtime libraries. +The EiffelCOM wizard is a powerful tool that enables both the rapid development of COM components in Eiffel and the access of COM components from Eiffel systems. The wizard consists of a series of input fields, in which you describe the component's characteristics. The wizard uses data you enter to produce: +# An Eiffel system skeleton +# The code to access or create a component +# The component-specific runtime libraries. -The wizard allows Eiffel developers with little COM knowledge to develop and reuse COM components. The design of the generated code follows the Eiffel standards and will be familiar to experienced Eiffel users. The only prerequisite to use the EiffelCOM wizard is an understanding of the '''Interface Definition Language'''. '''IDL''' describes a component. Compilers can generate '''Type Libraries''' from IDL files. Tools that need information on a given component, such as the EiffelCOM wizard, Visual Basic, etc. will analyze the Type Libraries. The IDL syntax is very close to C so should be easy to learn for developers that are familiar with this language. +The wizard allows Eiffel developers with little COM knowledge to develop and reuse COM components. The design of the generated code follows the Eiffel standards and will look familiar to experienced Eiffel users. The only prerequisite to use the EiffelCOM wizard is an understanding of the '''Interface Definition Language'''. '''IDL''' describes a component. Compilers can generate '''Type Libraries''' from IDL files. Tools that need information on a given component, such as the EiffelCOM wizard, Visual Basic, etc. will analyze the Type Libraries. The IDL syntax is very close to C so should be easy to learn for developers that are familiar with this language. The wizard generates code from a Type Library and additional information given by the user. The generated code consists of Eiffel classes, C/C++ files, and library files. The wizard automatically produces library files from generated C and C++ code. You do not need to modify generated C/C++ code to build your EiffelCOM system. ==Code Generation Process== - [[Image:introduction]] + +[[Image:introduction]] + + The wizard can automatically compile the generated C and Eiffel code. To produce a Type Library corresponding to a given IDL file the wizard relies on '''MIDL''', the Microsoft IDL compiler. You may also provide the wizard with a Type Library directly. The wizard can also be used to add a COM interface to an existing Eiffel project. For the rest of the manual a '''COM Definition File''' will refer to the input file given to the wizard (either an IDL file, a Type Library or an Eiffel project file). {{seealso|[[EiffelCOM Wizard Guided Tour|Guided Tour]] , [[EiffelCOM Wizard Reference|EiffelCOM wizard reference]] }}