views:

5119

answers:

2

Disclaimer: Near zero with marshalling concepts..

I have a struct B that contains a string + an array of structs C. I need to send this across the giant interop chasm to a COM - C++ consumer.
What are the right set of attributes I need to decorate my struct definition ?

[ComVisible (true)]
[StructLayout(LayoutKind.Sequential)]
public struct A
{
    public string strA
    public B b;
}


[ComVisible (true)]
[StructLayout(LayoutKind.Sequential)]
public struct B
{
    public int Count;

    [MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.Struct, SizeParamIndex=0)]
    public C [] c;
}

[ComVisible (true)]
[StructLayout(LayoutKind.Sequential)]
public struct C
{
    public string strVar;
}

edit: @Andrew Basically this is my friends' problem. He has this thing working in .Net - He does some automagic to have the .tlb/.tlh created that he can then use in the C++ realm. Trouble is he can't fix the array size.

+1  A: 

The answer depends on what the native definitions are that you are trying to marshal too. You haven't provided enough information for anyone to be able to really help.

A common thing that trips people up when marshalling strings in native arrays is that native arrays often use a fixed-size buffer for the string that is allocated inline with the struct. Your definition is marshalling the strings as a pointer to another block of memory containing the string (which is the default).

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = ##)] might be what you are looking for...

Andrew
+3  A: 

C++: The Most Powerful Language for .NET Framework Programming

I was about to approach a project that needed to marshal structured data across the C++/C# boundary, but I found what could be a better way (especially if you know C++ and like learning new programming languages). If you have access to Visual Studio 2005 or above you might consider using C++/CLI rather than marshaling. It basically allows you to create this magic hybrid .NET/native class library that's 100% compatible with C# (as if you had written everything in C#, for the purposes of consuming it in another C# project) that is also 100% compatible with C and/or C++. In your case you could write a C++/CLI wrapper that marshaled the data from C++ in memory to CLI in memory types.

I've had pretty good luck with this, using pure C++ code to read and write out datafiles (this could be a third party library of some kind, even), and then my C++/CLI code converts (copies) the C++ data into .NET types, in memory, which can be consumed directly as if I had written the read/write library in C#. For me the only barrier was syntax, since you have to learn the CLI extensions to C++. I wish I'd had StackOverflow to ask syntax questions, back when I was learning this!

In return for trudging through the syntax, you learn probably the most powerful programming language imaginable. Think about it: the elegance and sanity of C# and the .NET libraries, and the low level and native library compatibility of C++. You wouldn't want to write all your projects in C++/CLI but it's great for getting C++ data into C#/.NET projects. It "just works."

Tutorial:

Jared Updike