Understanding interface marshaling

There is quite a lot of misunderstanding among COM newbies about what really happens when a COM interface is passed as a method parameter. As in most of the cases, VB programmers are protected from a lot of details on the COM run-time, but you do have to know such details if you want to assemble something that perform decently in a distributed environment.

1) Basic automation types (Double, Long, String) are passed by value if the method signature is declared ByVal. They are passed by reference if the method signature is declared ByRef. The behavior you experience is the same if the method call takes place in-Apartment or cross-Apartment.
2) COM Interfaces: The first thing to emphasize here is that in VB (or in any COM-aware language) you never get in touch with a Class (the client doesn’t have to know the class binary layout!); instead, you get in touch with interfaces. So when you think you’re passing an object you are actually passing an interface. The state of underlying COM object that is behind the interface is not copied, e.g. as a struct (a VB type) is.

Now, coming to the point: COM Interfaces are passed

a) by reference if the method signature is declared ByVal;
b) by a reference to a reference if the method signature is declared ByRef.

For example, the following VB procedure signature:

Public Sub test(ByVal a1 As IMyInterface1, ByRef a2 As IMyinterface2)

maps to the following IDL code:

HRESULT test([in] IMyInterface* a1,[in,out] IMyInterface2** a2);

This means that even if you pass an interface ByVal, you shouldn’t to be surprised that, on returning from the method call, one of its properties have been changed.

You might wonder when ByRef makes the difference: Passing an interface ByRef lets the callee replace the object behind the interface with another object that implements the same interface. Here an example: Say that CFastAnimal and CSlowAnimal both implement the interface IRun. CSomething implements IPrepareToRun, which has two methods : PrepareByRef and PrepareByVal:

Public Sub PrepareByRef(ByRef a1 As IRun)     Set a1 = CreateObject("CSlowAnimal")    a1.name = "AAA"End SubPublic Sub PrepareByVal(ByVal a1 As IRun)     Set a1 = Createobject("CSlowAnimal")    a1.name = "AAA"End Sub

Here is the client code:

Sub a()    Dim x As IRun    Set x = CreateObject("CFastAnimal")     x.name ="BBB"    Dim y As IPrepareToRun    Set y = CreateObject("CSomething")     y.PrepareByRef(x)     x.run                  'runs slow    Debug.Print x.name     'prints "AA"End SubSub b()    Dim x As IRun    Set x = CreateObject("CFastAnimal")     x.name ="BBB"    Dim y As IPrepareToRun    Set y = CreateObject("CSomething")     y.PrepareByVal(x)    x.run                  'runs fast    Debug.Print x.name     'prints "AA"End Sub

You see the same behavior described above if you pass Interfaces in-Apartment or cross-Apartment (Cross Process / Cross Host) if such interface are standard marshaled (Type-Library marshaling).

I should stress, however, that passing interfaces across apartment boundaries is considered bad design (especially across hosts): reading or setting a property involves a roundtrip. There are some cases where you may need to pass an interface for a callback, but NEVER use an interface as a method to pass/return data among two objects if you are not sure the two objects and the interface in question will always be in the same apartment.

There is an exception, though: you can do it if the interface implements MBV (Marshaling by value), and , yes, ADO disconnected Recordsets do implement marshaling by value. This means that when the _Recordset interface crosses apartment boundaries the data behind the recordset are copied in the new apartment. If the parameter is declared ByRef, then the data are copied back. But remember: this happens only if the recordset cross apartment boundaries, if it’s not the case you get the standard COM behavior.

The conclusions are:

1) you have to know what standard marshaling is to develop distributed application;
2) you have to know when an interface is MBV and be aware that, in such case, your object behaves differently when is passed in-Apartment or inter-Apartment.

Share the Post:
Share on facebook
Share on twitter
Share on linkedin

Overview

The Latest

homes in the real estate industry

Exploring the Latest Tech Trends Impacting the Real Estate Industry

The real estate industry is changing thanks to the newest technological advancements. These new developments — from blockchain and AI to virtual reality and 3D printing — are poised to change how we buy and sell homes. Real estate brokers, buyers, sellers, wholesale real estate professionals, fix and flippers, and beyond may

man on floor with data

DevX Quick Guide to Data Ingestion

One of the biggest trends of the 21st century is the massive surge in internet usage. With major innovations such as smart technology, social media, and online shopping sites, the internet has become an essential part of everyday life for a large portion of the population. Due to this internet

payment via phone

7 Ways Technology Has Changed Traditional Payments

In today’s digital world, technology has changed how we make payments. From contactless cards to mobile wallets, it’s now easier to pay for goods and services without carrying cash or using a checkbook. This article will look at seven of the most significant ways technology has transformed traditional payment methods.