.NET     Console.WriteLine( "All Things .NET" );
.NET Nerd Blog Home
2.08.2005

 
COM Interop with size_is
I'm sure I'll need this someday if I ever get back into COM interop. Calling a COM method that has an outbound array using the size_is MIDL attribute.

The size_is keyword is lost when creating a type library, so the .NET marshaller cannot map the array length back into managed code. To get around this, you have to use IntPtr, then use the Marshal class to convert the returned buffer into array elements.

(Original article thanks to www.thinkdotnet.com which I think is dead now.)

keywords: com interop midl size_is array structs structures
typedef struct ASTRUCT

{
[string] OLECHAR* str;
long theLong;
};

[
object,
uuid(09db9b39-35c7-49e0-b7c4-a4bbdad4ea05),
pointer_default(unique)
]
interface IStructTester : IUnknown
{
HRESULT GetArrayOfStructs( [out] long* pCount,
[out,size_is(,*pCount)] AStruct** ppStructs );
}

[ StructLayout( LayoutKind.Sequential ) ]
public struct ASTRUCT
{
[MarshalAs( UnmanagedType.LPWStr )]
public String str;
public long theLong;
}

[InterfaceType(ComInterfaceType.InterfaceIsIUnknown),
Guid("09db9b39-35c7-49e0-b7c4-a4bbdad4ea05")]
{
[PreserveSig(true)]
void GetArrayOfStructs( out Int32 pCount, out IntPtr buffer );
}

IntPtr buffer;
Int count = 0;

IStructTester theInterface = (IStructTester)new StructTester();
theInterface.GetArrayOfStructs( ref count, out buffer );

// allocate the managed array
ASTRUCT[] managedArray = new ASTRUCT[count];

// now copy the array elements one-by-one, using the IntPtr buffer
for ( int i=0; i<count; i++ )
{
managedArray[i] = (ASTRUCT)Marshal.PtrToStructure( (int)buffer,
typeof(ASTRUCT) );
buffer = (IntPtr)((long)buffer + Marshal.SizeOf(managedArray[0]));
}



Comments: Post a Comment

Powered by Blogger