1

I have a C++ COM server that fills a C# caller's structure with data.

The structure is defined in the C++ IDL, something like the following:

interface Icontrol : IDispatch{
    [ 
    uuid(...), 
    version(1.0) ]
    typedef struct testStructure
    { 
        int x;
        int y;
        int z;
        ...
    } testStructure; 

    ...
    [id(9)] HRESULT getStruct([ref,in,out] testStructure * theData);
    ...

Then, in the C# code:

EO_Lib.testStructure test = new EO_Lib.testStructure();
EO_Lib.getStruct(ref test);

I can make this work no problem with a regular .DLL by simply using MarshallAs in a C# structure for the fields non-native to C#. But I can't get that to work on a COM .DLL. I suspect it's because of my lack of knowledge about IDL.

What I need to be able to do is call getStruct() with a new C# type that I've created with appropriate MarshallAs() information. How do I do this?

I am using Visual Studio 2010 MFC/ATL C++ and C# .NET 4 Framework, if it helps.

kmort
  • 2,848
  • 2
  • 32
  • 54

2 Answers2

0

While not an actual solution to the question, the following obviates the reason for my question.

From: http://msdn.microsoft.com/en-us/library/75dwhxf7(v=vs.100).aspx

Structures that are returned from platform invoke calls must be blittable types. Platform invoke does not support non-blittable structures as return types.

So basically, you can't do what I wanted to do.

If you ignore the COM aspect, BrokenGlass's solution here answers the convert-one-structure-to-another question.

Community
  • 1
  • 1
kmort
  • 2,848
  • 2
  • 32
  • 54
0

It sounds like you are trying to tackle this from the Managed side of things. Not knowing many details about your architecture (like is this your COM server, as in you wrote it/own the code?) I'm going to have to make some assumptions in order to provide any solutions that approach from the C++ side, specifically the MIDL (IDL) aspect.

You mention the IDL and from what I can tell, at the very least you have access to the IDL that generates the type library. So, forget about what the CLR (managed) side for a bit and get it all working in the un-managed environments (COM).

Once that is done, determine what you want the struct to look like for your managed clients. Using that information, define a new type in your C++/MIDL project(s). If you don't have an ACF (Application Config File) file for your IDL, create one (its just an IDL file with the exact same name but with an ".acf" extension instead of ".idl". In the ACF file declare a user_marshal type that maps your COM struct to the new "managed friendly" struct that you just defined. Something like this:

// ACF file

typedef [user_marshal(testStructure_ForDotNet)] testStructure;

// where testStructure is your "original" struct and "testStructure_ForDotNet" 
// is the one you just defined.

Finally, you'll need to define your conversion functions (Marshaling functions). Refer to this resource for more information:

http://msdn.microsoft.com/en-us/library/windows/desktop/aa367296(v=vs.85).aspx

Anyway, hope that helps (anyone).

Paul Easter
  • 631
  • 6
  • 5