65.9K
CodeProject is changing. Read more.
Home

Editing the Interop Assembly to Pass Array from COM DLL to C# App and Vice Versa

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.25/5 (6 votes)

Nov 23, 2005

CPOL

1 min read

viewsIcon

55022

downloadIcon

331

This article shows how to change the COM method signature by editing the Interop assembly

Please review the demo code before you read the article.

Introduction

The first step to connect between .NET components and COM components is to create an RCW, by:

  1. Using the references dialog box of Visual Studio .NET, or
  2. Using the TLBIMP command-line tool

The type library importer converts most COM method signatures into managed signatures, but it might not always be appropriate for the COM component. Here I describe how to modify the metadata inside the interop assembly.

Specify Marshaling Changes in Microsoft Intermediate Language (MSIL)

  1. Generate the initial interop assembly using Visual Studio .NET. For example, add reference to MarshallingTest.dll and you will note that MARSHALLINGTEST reference has been added to your solution. You can use tlbimp.exe tool:

    tlbimp MarshallingTest.tlb /out:MarshallingTest.dll
  2. At the command prompt, type the following command to produce Microsoft intermediate language (MSIL) for the assembly:

    ildasm MarshallingTest.dll /out:MarshallingTest.il
  3. Edit the MSIL (MarshallingTest.il) :

    Here you should make your correction, search for...

    .method public hidebysig newslot virtual instance 
       void SetSurface(int32 size, native int pSurface) 
       runtime managed internalcall

    ... and make the following change:

    .method public hidebysig newslot virtual instance 
       void SetSurface(int32 size, native int & pSurface) 
       runtime managed internalcall

    Then, search for:

    .method public hidebysig newslot virtual instance 
       void GetSurface([out] int32& size, [out] native int pSurface) 
       runtime managed internalcall

    Change to:

    .method public hidebysig newslot virtual instance 
       void GetSurface([out] int32& size, [out] native int & pSurface) 
       runtime managed internalcall
  4. At the command prompt, type the following command to produce a new MarshallingTest.dll defining the proper syntax:

    ilasm /DLL MarshallingTest.il
  5. Delete the old reference to the MARSHALLINGTEST and add a new reference for the new DLL that was generated using ilasm.exe (step 4).

Inside the Code

This code shows how to connect to a COM object from a C# application and how to allocate the Marshalling memory before the get/set call:

Sample screenshot

Note that the StructureToPtr member function converts an array of structures to block of memory using the Marshal.AllocCoTaskMem method.

Also note that during the GetSurface call, the memory allocation is done on the COM side. So, the C# side is responsible for freeing this memory.