0

I have an ATL COM object that I am using from C#. The interface currently looks like:

interface ICHASCom : IDispatch{
    [id(1), helpstring("method Start")] HRESULT Start([in] BSTR name, [out,retval] VARIANT_BOOL* result);
...
    [id(4), helpstring("method GetCount")] HRESULT GetCount([out,retval] LONG* numPorts);
...

    [id(7), helpstring("method EnableLogging")] HRESULT EnableLogging([in] VARIANT_BOOL enableLogging);
};

That is, it's a very simple interface. I also have some events that I send back too. Now, I would like to add something to the interface. In the ATL I have some results, which are currently structs and look like struct REPORT_LINE { string creationDate; string Id; string summary; }; All the members of the struct are std::string. I have an array of these that I need to get back to the C#. What's the best way to do this?

I suspect someone is going to say, "hey, you can't just send std::string over COM like that. If so, fine, but what's the best way to modidfy the struct? Change the std::string to BSTR? And then how do I, 1) Set up the IDL to pass an array of structs (structs with BSTR or std::string) 2) If I must use SAFEARRAYS, how do I fill the SAFEARRAYS with the structs.

I'm not familiar with COM except for use with simple types.

Justin
  • 84,773
  • 49
  • 224
  • 367
Dave
  • 8,095
  • 14
  • 56
  • 99

1 Answers1

1

a user defined structure is incompatible with the automation interface. You can probably work out a nested array or two dimensional safe array of BSTRs, but a more maintainable solution would be wrapping the structure as an automation object with 3 properties, then wrap the array as a collection that has an enumerator.

Neither IDL nor Automation define byte alignment for a struct. So you can have compatibility problems if your COM server has different struct alignment with the client. e.g. VB has a 4-byte alignment, while the #import in Visual C++ default to a 8-byte alignment. If you have a slightest chance in the future to use the interface in scripting, avoid using structs.

Suggested reading:

Sheng Jiang 蒋晟
  • 15,125
  • 2
  • 28
  • 46
  • Thanks for the quick response, I am reading your suggestions. One quick question: I played some more and was able to come up with the following: interface ISimpleCom : IDispatch{ [id(1), helpstring("method Test2")] HRESULT Test2([in,out] SAFEARRAY(struct MyStruct) param); }; where MyStruct is: struct MyStruct { long nLongValue; BSTR bstrStringValue; } ; This worked fine from C#. It should not have based on your suggestions and reading (or is SAFEARRAY automation compliant?). C#: SafeArrayPlayLib.MyStruct[] myArray = new MyStruct[2]; com.Test2(myArray); Regards,Dave – Dave May 07 '10 at 15:44
  • Thanks Sheng. I won't be using this COM component with Script, just C#. Thanks for all the help. It's hard to get help on COM these days; it's old technology. – Dave May 07 '10 at 22:54