Friday, July 13, 2007

Marshalling Arrays To VB6's COM Funland pt2

Ok, yesterday I figured out how to get an array of interfaces (actually, objects that implement an interface, but go along with my sloppy grammer, ok?) out of C#, through the COM Callable Wrapper (CCW) and into COM-land.

Wouldn't you know it, but I also need to be able to pass an array of objects back into C# from COM-land.

Well, I'm here to say that figuring this out was a lot easier than yesterday's problem. At first I tried something like:

Hooray! That works! The array gets passed back into .NET-land, and things seem happy. Except, I wouldn't be writing this post if I didn't have a problem, right? Well, TakeBusinessObjects(...) doesn't throw an exception, and it reaches it's return statement successfully. Unfortunately, something gets lost in translation while returning control to VB6-land because I intermediately upon returning, VB6 raises this error:

Class does not support Automation or does not support expected interfaceNumber: 430

This error makes it sound like I've developed on v2 of some COM component, but I've deployed the compiled EXE on a machine that only has v1 of the COM component. What I don't understand is that the array gets passed through the CCW into .NET-land! It works! Something just goes wrong on the way back to VB-land.

Update: The Answer! (Kind of)

I gotta hand it to my buddy Jimmy - that guy has given me the "Try XYZ" that has fixed whatever problem I was tackling so many times -- and he's come through once again! He suggested that, I take a look at the [In] and [Out] attributes.

By default, when I compile my COM component, it's being assumed that I not only want to be able to take in an array reference, but that I also want to push any changes made to that array reference back out to the caller. Well, lucky for me, I don't make any changes to the array once it's in .NET-land, and I can flag the parameter as only needing to come into the method, and not out. Like this:

So, while this fixes most of the situations where I would need to pass an array from COM-land into .NET-land, it still irks me that I don't know why VB6 throws that error if the CCW marshaller tries to move the array back out of .NET-land when the method returns.