1

We have a legacy COM DLL with the following simplified IDL for some method:

AllocateMemory( [in] LONG lSize, [out] LONG *pAddr );

Implementation of this method contains the following:

BYTE *pArr = (BYTE*)CoTaskMemAlloc( lSize );  
*pAddr = &pArr;  

The address of newly allocated memory is returned as a long value back to the caller.

C++ clients utilizing this COM object can invoke that method and then access the memory as follows:

//---- C++ ----------------   
long lSize = 10;  
long lAddr;  
pCOMObj->AllocateMemory( lSize, &lAddr );  
byte **bArray = (byte**)lAddr;  
for (int i = 0; i < iSize; i++)  
{  
    printf( "array[%d] = %d\n", i, (*bArray)[i] );  
}  
// Now deallocate memory.  
CoTaskMemFree( *bArray ); 
//--------------------

All works well from C++ COM client.

The same COM DLL was added as a reference to a Visual Studio 2010 project.
Our goal is to be able to do the same from C# client using Interop:

//---- 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 < iSize; i++)  
   Console.WriteLine( bArray[i] );  

// Release the unmanaged array.  
Marshal.FreeCoTaskMem( rAddr );  
//--------------------

Does anyone know of a potential solution?

3
  • &pArr - return address of local temporary variable? Commented Mar 18, 2012 at 0:36
  • It would be helpful if you said what about your proposed method did not work. Commented Mar 18, 2012 at 0:56
  • Thanks for the suggestion - I updated the post. In essence, 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. Commented Mar 18, 2012 at 1:08

3 Answers 3

1
IntPtr bAddr = new IntPtr( iAddr );  // bAddr = (byte**)iAddr
IntPtr rAddr = new IntPtr(Marshal.ReadInt32(bAddr)); //rAddr = (*bAddr);

byte [] bArray = new byte [iSize];   
// Marshal the array from an unmanaged to a managed heap.   
Marshal.Copy( rAddr, bArray, 0, iSize );   
for (int i=0; i < iSize; i++)   
   Console.WriteLine( bArray[i] );   

// Release the unmanaged array.   
Marshal.FreeCoTaskMem( rAddr );  
Sign up to request clarification or add additional context in comments.

Comments

0

Firstly, you must build as only x86- that code will fail on 64bit. Secondly, you must use unsafe code to perform such a conversion in C#.

1 Comment

I didn't try with 64-bit code yet, though it does work fine as DarkGray indicated without unsafe code.
0

There is a ReadIntPtr method to read a native width pointer from an address. It will work on both architectures, unlike ReadInt32

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.