I'm trying to marshal memory allocated in C++ DLL to a C# component.
The code I'm using is as follows:
void Initialise( HGLOBAL* phBuffer, DWORD* pdwLength )
{
CSharedFile mout( GHND );
CArchive arout( &mout, CArchive::store );
// Write some stuff to the archive...
arout.Close( );
*pdwLength = mout.GetLength( );
*phBuffer = mout.Detach( );
}
C# code is...
ref byte[] data
Int32 dataLength = 0;
IntPtr rawData = IntPtr.Zero;
if( NativeMethods.Initialise( ref rawData, ref dataLength ) != 0 )
{
return;
}
data = new Byte[dataLength];
Marshal.Copy( rawData, data, 0, dataLength );
Marshal.FreeHGlobal( rawData );
The code compiles and runs, but I've noticed the following:
* If I allocate the memory with the GPTR flag instead of GHND, the code
will run ~50% of the time correctly. The rest of the time it fails in
the C++ code with a memory exception, probably because GPTR is
non-movable memory and it was not possible to re-allocate without
moving the memory. However, the 50% of the time when this doesn't
happen, the C# marshalling code works and my data is correct.
* If I allocate the memory with a GHND flag, the C++ code never
crashes, but the marshalling always fails in the C#. That is, there are
no exceptions or errors (even on the FreeHGlobal), but the data
variable has junk in it.
I think I'm missing a trick here... perhaps rawData should not be
IntPtr type? Any help would be greatly appreciated!
--
Martin Hignett
Mattias Sjögren - 04 Jan 2007 20:26 GMT
Martin,
>* If I allocate the memory with a GHND flag, the C++ code never
>crashes, but the marshalling always fails in the C#. That is, there are
>no exceptions or errors (even on the FreeHGlobal), but the data
>variable has junk in it.
In this case you have to use GlobalLock to get a pointer to the data,
you can't pass the HGLOBAl directly to Marshal.Copy.
Mattias

Signature
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.
Martin Hignett - 05 Jan 2007 11:29 GMT
> Martin,
>
[quoted text clipped - 12 lines]
> http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
> Please reply only to the newsgroup.
That has fixed the problem, thanks! I had it in my mind that Marshal
would somehow know it was global memory and call
GlobalLock/GlobalUnlock appropriately.
Took a quick look at your website too and I have to say it looks like a
fantastic resource for people battling with C# interoperability issues!
Thanks!
--
Martin Hignett
Mattias Sjögren - 09 Jan 2007 21:40 GMT
Martin,
>Took a quick look at your website too and I have to say it looks like a
>fantastic resource for people battling with C# interoperability issues!
Thanks, I'm glad you found it useful. I just wish I had time to update
it.
Mattias

Signature
Mattias Sjögren [C# MVP] mattias @ mvps.org
http://www.msjogren.net/dotnet/ | http://www.dotnetinterop.com
Please reply only to the newsgroup.