Understanding interface marshaling

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:
Heading photo, Metadata.

What is Metadata?

What is metadata? Well, It’s an odd concept to wrap your head around. Metadata is essentially the secondary layer of data that tracks details about the “regular” data. The regular

XDR solutions

The Benefits of Using XDR Solutions

Cybercriminals constantly adapt their strategies, developing newer, more powerful, and intelligent ways to attack your network. Since security professionals must innovate as well, more conventional endpoint detection solutions have evolved

AI is revolutionizing fraud detection

How AI is Revolutionizing Fraud Detection

Artificial intelligence – commonly known as AI – means a form of technology with multiple uses. As a result, it has become extremely valuable to a number of businesses across

AI innovation

Companies Leading AI Innovation in 2023

Artificial intelligence (AI) has been transforming industries and revolutionizing business operations. AI’s potential to enhance efficiency and productivity has become crucial to many businesses. As we move into 2023, several

data fivetran pricing

Fivetran Pricing Explained

One of the biggest trends of the 21st century is the massive surge in analytics. Analytics is the process of utilizing data to drive future decision-making. With so much of

kubernetes logging

Kubernetes Logging: What You Need to Know

Kubernetes from Google is one of the most popular open-source and free container management solutions made to make managing and deploying applications easier. It has a solid architecture that makes