top header
apartmentsterm

 

home contents introduction com as a better C++ interfaces classes apartments labs lab setup quizzes
 
previousnext

 
Standard Marshalling

Recall that there are two good reasons for us to concentrate on standard marshalling:

  • Because it is easy. The object implementor need do nothing but design the interfaces to be remoted in IDL.
  • The implementation of standard marshalling is tightly coupled to the notion of maintaining object identity across context.

We saw that CoMarshalInterface() and CoUnmarshalInterface() are used to export an interface pointers from one context and import into another. If an object doesn't implement the IMarshal interface, the COM run-time¡¯s "standard marshaller" will be used to export and import interface references to the object. All references to marshalling and unmarshalling in this section assume the use of the COM runtime¡¯s "standard marshaller".

Standard marshalling will perform the following tasks.

  • Create a STDOBJREF for transmission.
  • Create a stub in the object's context to receive incoming ORPC request packets from the proxy.
  • Create a proxy in the caller's context that feels exactly like the real object but sends/receives ORPC request/response packets in lieu of performing actual operations.
    • The proxy and stub communicate via a system provided channel that abstracts the exact underlying communication mechanism. This channel is sensitive to the exact difference in context that exists between the proxy and stub.

Marshalling an interface: STDOBJREF, interface stubs and the stub manager

Under standard marshalling, CoMarshalInterface creates two things for each marshalled interface on an object:

  1. A standard OBJREF, STDOBJREF, which is the marshalled data for the interface, enough to unmarshall into a proxy.
  2. An interface stub. A stub for a given interface holds on to a direct in-context reference to that interface on the real object. It listens on the system-supplied communications channel that connects the proxy and stub. The interface stub intercepts ORPC requests from the proxy and translates them into method invocations on the real object. For the first interface reference that is marshalled for an object identity, the standard marshaller will also set up a stub manager, that looks after all the interface stubs.

Here is a diagram outlining the relationship between the stub manager, the interface stubs and the real object. All are in the object's context.

apartments11.gif

The STDOBJREF

Here is a diagram of the OBJREF that standard marshalling builds - the STDOBJREF.

apartments12.gif

The important things to notice are

  • A flag that indicates whether we are using standard, custom or handler marshalling. This dictates the layout of most of the rest of the OBJREF. Because we are discussing standard marshalling then the format will be as above.
  • The interface IID, which is used to identify the type of interface that has been marshalled. For standard marshalling this is used as the registry key to work out which proxy to load in the caller's context and which stub to load in the object's context. This assumes both have been registered correctly.
  • The OXID, which is a machine-wide unique object exporter ID on the exporting machine. It is used to identify where the STDOBJREF was exported from, i.e. where the object lives. OXIDs provide two things.
    • OXIDs provide a container or scope for grouping together objects. In theory an OXID defines a context-based sub-division of a process that represents the unique location that calls to an object can be dispatched (executed). In reality it defines an apartment under the current implementation of COM.
    • OXIDs enable lazy resolution (at or before the first method call) of the communications protocol used to bind to an object's exporter and make calls on the object. This is done via a service on the exporting machine called the OXID Resolver, discussed later. The OXID is generated the first time an interface is exported from an apartment. It is registered in a table held by the OXID Resolver on the exporting machine, along with the protocol information needed to bind to the object exporter locally.
  • The OID, which is a context-wide unique object instance ID. This is used in the caller's context for maintaining remote object identity.
  • The IPID, which is a context-wide unique interface stub identifier. Once the OXID has been used to establish a connection with an object's exporter (apartment) in the object's server on a particular machine, the IPID will get us back to a particular interface stub on a particular object in a particular context in the object's context.
  • The host address determines the exporting machine that must be used to resolve the OXID into the communications protocol-specific address used to communicate with the object, in the case where the OBREF is imported on a foreign machine.

The standard marshaller uses the interface IID as a key to search the registry for the stub class to load. Here is a diagram showing the registry key for an interface IFoo. This is the registry of the exporting machine.

apartments13.gif

The CLSID of the stub is shown by the ProxyStubClsid32 key thus.

apartments14.gif

The registry entry for the stub's CLSID looks like this.

apartments19.gif

The standard marshaller uses this CLSID to load a code for the stub class. Notice that the stub class is just a regular COM class and that it is marked as threading model "Both", which simply means that the stub (and proxy) code can be loaded directly into any threading environment (more on the ThreadingModel attribute later).

Unmarshalling an interface: proxies and the proxy manager

COM ensures that an interface proxy exists for each marshalled interface reference that is unmarshalled. The interface proxy is connected to the stub via a system-supplied channel. The interface proxy is held by the caller that unmarshalls it as a direct in-context reference. From the caller¡¯s perspective, the proxy looks and feels just like the real interface implementation on the real object. In reality, the proxy dehydrates the method calls into ORPC requests that are sent to the connected interface stub. The proxy then waits for the ORPC response, which it rehydrates in order to return the results of the method to the caller. For the first interface reference that is unmarshalled on a given object identity (in a given context), the standard marshaller will set up a proxy manager that looks after all the proxies. The proxy manager represents the remote object's identity in the caller's context.

Here is a diagram outlining the relationship between the caller, the proxy manager and the aggregated interface proxies. All are in the caller's context.

apartments15.gif

When unmarshalling, the standard marshaller uses the interface ID in the OBJREF as a key to search the registry for the proxy class to load.

Putting it all together

Here is the whole picture.

apartments17.gif

Click here to see an animation which shows the sequence of events that occurs when an interface reference is passed as a parameter to a method of an interface which is already remoted.

Next we look at how to generate proxies and stubs for standard marshalling.


Top of document