7
votes

I'm trying to use a COM interface from C# that exposes the following interface as generated by tlbimp:

[Guid("7DDCEDF4-3B78-460E-BB34-C7496FD3CD56")]
[TypeLibType(TypeLibTypeFlags.FDual | TypeLibTypeFlags.FNonExtensible | TypeLibTypeFlags.FDispatchable)]
public interface IFred 
{
    [DispId(1)]
    IBarney Pall { get; set; }
}

[Guid("E390230E-EE9C-4819-BC19-08DAB808AEA9")]
[TypeLibType(TypeLibTypeFlags.FDual | TypeLibTypeFlags.FNonExtensible | TypeLibTypeFlags.FDispatchable)]
public interface IBarney
{
    [DispId(1)]
    double Wilma { get; set; }
}

The generated wrapper assembly does not contain an implementation for the IBarney interface. I've created a C# structure that implements the IBarney interface like this:

[Guid("2C61BA37-7047-43DB-84B1-83B4268CF77B")]
[ComVisible(true)]
public struct Barney : IBarney
{
    public double Wilma { get; set; }
}

Which "works", the question now is, will a Barney instance be marshalled by value or by reference? This is important due to the network overhead involved. Ideally executing something like:

fredInstance.Pall = new Barney { Wilma = 0.37 };

will result in a single network round trip. How can I verify this, or how can I tell COM interop my Barney structure should always be marshalled by value?

Update:

Given the comment from Hans Passant. What would be the 'proper' way to design this? What would be the IDL needed to allow for a simple structure to be usable as a value for a 'property' of a COM interface? Looking at the IDL from which the interfaces are generated that I'm currently using adding a coclass declaration with a default IBarney interface would be enough, right?

1
No need to check, COM never cares how an object is implemented and only works with interface pointers. This will be roundtrip for each property access. Technically that can be addressed with a custom proxy/stub but that is out of reach from .NET. Consider implementing IPersistStream.Hans Passant
@HansPassant: I'm guessing you mean implementing IPersistStream on the COM/native side? Since googling for it only reveals, references to non .NET stuff.Bas Bossink
Are you working in C# on both ends? or is there any other language involved? ie: why are you creating COM interfaces in the first place? Why do you use idl to define your interface? Do you need automation compatible interfaces? are you aware of the difference between "pure" COM and COM+automation?Simon Mourier
I'm working in a company that works both in .NET and in C++ and the interop between the two worlds is done using COM. I'm personally involved in the .NET development. To change the IDL/COM parts some negotiation has to take place but in principle they can be changed. One of the original requirements for the COM interfaces was that they are OLE automation compatible. I'm (as you might guess) not knowledgeable on COM, I don't know about the distinction between COM and COM+ automation. Any pointers to resources are appreciated.Bas Bossink
ok, so you need C++, and Automation (I was not talking about COM+, but COM + Automation :-). In this case, you have to know Automation will reduce considerably the types you can use (it has its advantages also): msdn.microsoft.com/en-us/library/cc237562.aspx (beware, VT_RECORD is not supported by all clients, it was a late addition). The simplest is to use a SAFEARRAY (of UI1), or a VARIANT (can wrap any automation type). PS: dont' forget to add @ <user> when you want to address a comment. I just passed by and noticed you answered meSimon Mourier

1 Answers

1
votes

A couple comments... Don't know if this will be an answer or not...

1) I would think that you should make your interfaces [ComVisible(true)]

2) Why do you define Barney as a struct? It should be a class. Unlike C++ where the only difference between a class and a struct is the default of private vs public members, C# structs and classes are fundamentally different.