title: Accessing unmanaged memory by address allocated in COM / C++ from C# via Interop
body: <p>We have a legacy COM DLL with the following simplified IDL for some method:</p>
  
  <pre><code>AllocateMemory( [in] LONG lSize, [out] LONG *pAddr );
  </code></pre>
  
  <p>Implementation of this method contains the following:</p>
  
  <pre><code>BYTE *pArr = (BYTE*)CoTaskMemAlloc( lSize );  
  *pAddr = &amp;pArr;  
  </code></pre>
  
  <p>The address of newly allocated memory is returned as a long value back to the caller.</p>
  
  <p>C++ clients utilizing this COM object can invoke that method and then access the memory as follows:</p>
  
  <pre><code>//---- C++ ----------------   
  long lSize = 10;  
  long lAddr;  
  pCOMObj-&gt;AllocateMemory( lSize, &amp;lAddr );  
  byte **bArray = (byte**)lAddr;  
  for (int i = 0; i &lt; iSize; i++)  
  {  
      printf( "array[%d] = %d\n", i, (*bArray)[i] );  
  }  
  // Now deallocate memory.  
  CoTaskMemFree( *bArray ); 
  //--------------------
  </code></pre>
  
  <p>All works well from C++ COM client. </p>
  
  <p>The same COM DLL was added as a reference to a Visual Studio 2010 project.<br>
  Our goal is to be able to do the same from C# client using Interop:</p>
  
  <pre><code>//---- C# ----------------  
  int iSize = 10;  
  int iAddr = 0;  
  objCOM.AllocateMemory( iSize, ref iAddr );  
  ...    
  
  // ??? *UNKNOWN*  
  // At this point we need to be able to access allocated memory pointed to by iAddr.  
  
  
  // The following does NOT work, i.e., no errors occur but array contents are totally
  // different from what has been initialized inside AllocateMemory() method, implying 
  // that totally different memory is being accessed/copied:    
  byte [] bArray = new byte [iSize];  
  IntPtr rAddr = new IntPtr( iAddr );  
  
  // Marshal the array from an unmanaged to a managed heap.  
  Marshal.Copy( rAddr, bArray, 0, iSize );  
  for (int i=0; i &lt; iSize; i++)  
     Console.WriteLine( bArray[i] );  
  
  // Release the unmanaged array.  
  Marshal.FreeCoTaskMem( rAddr );  
  //--------------------
  </code></pre>
  
  <p>Does anyone know of a potential solution?</p>