tags:

views:

213

answers:

2

What's the best way to get a chunk of memory (i.e. void*) from a COM server to C#?

We have been using an IStream (using CreateStreamOnHGlobal) and passing that back, which worked. However when we tried this on x64 CLR with x32 C++ COM it blows up.

The COM has to be x32 because it uses external 32 bit DLLs. The C# could be forced to run 32 bit but the challenge is to keep that running as x64.

A: 

If you have .NET 3.5, have a look at System.IO.Pipes- create a well-known pipe name and squirt it over from unmanaged code with the Win32 named pipes APIs.

nitzmahone
Sadly we're on .NET 2.0 still (customers sometimes still don't like having to install 3.5 - when windows 7 takes hold most will have it anyway. People not installing vista delayed it's take up)
MrPurpleStreak
+1  A: 

Answering my own question.

When you return an IStream from your own COM server the .NET interop DLL puts an IStream into it's interface. For example lets say the type library is MyComServer, then the interop will contain a class MyComServer.Interop.IStream.

this IStream class has functions like RemoteRead, RemoteWrite etc. These take a ref byte as the first parameter. Using these worked fine on 32bit to 32bit, but that ref probably becomes a pointer and so on 64 to 32 something went wrong.

The solution is to convert the MyComServer.Interop.IStream to System.Runtime.InteropServices.ComTypes.IStream using "as" (or just cast probably). This then takes a more familiar byte[], int count and IntPtr for the return size.

The IntPtr is annoying as it could be an out int, but I used (typing this in by hand so not compiler checked..)

byte[] buffer = new byte[100];
IntPtr ptr = Marshall.AllocHGlobal( sizeof(int) );
stream.Read( buffer, 100, ptr );
MrPurpleStreak