You cannot go through the CLI Memorystream . The best you can do is pass a pointer (IntPtr) to the byte buffer.
See How to transfer MemoryStream data to an unmanaged C ++ DLL using P / Invoke? for more details
I was able to get an example of work based on this post ( PInvoke and IStream ). Basically you need to implement the IStream interface in C #. You can then pass the custom Memorystream as LPSTREAM on the C ++ side. Here is an example of code that takes a stream and gets the size (just a trivial example to show how this is done):
C ++ LpWin32Dll.h
#ifndef LPWINDLL_H #define LPWINDLL_H extern "C" { __declspec(dllexport) int SizeOfLpStream(LPSTREAM lpStream); } #endif
C ++ LpWin32Dll.cpp
#include "stdafx.h" #include <ocidl.h> #include "LpWin32Dll.h" // Provides DllMain automatically [module(dll, name = "LpWin32Dll")]; __declspec(dllexport) int SizeOfLpStream(LPSTREAM lpStream) { STATSTG stat_info; lpStream->Stat(&stat_info, STATFLAG_NONAME); return stat_info.cbSize.LowPart; }
C # PInvoke Definition
[DllImport("LpWin32Dll.dll", CallingConvention=CallingConvention.StdCall)] public static extern int SizeOfLpStream(IStream iStream);
Implementation of C # IStream (must implement the IStream interface). I just created a wrapper class for the Memorystream class.
[ClassInterface(ClassInterfaceType.AutoDispatch)] public class IMemoryStream : MemoryStream, IStream { public IMemoryStream() : base() { } public IMemoryStream(byte[] data) : base(data) { } #region IStream Members public void Clone(out IStream ppstm) { ppstm = null; } public void Commit(int grfCommitFlags) { } public void CopyTo( IStream pstm, long cb, IntPtr pcbRead, IntPtr pcbWritten) { } public void LockRegion(long libOffset, long cb, int dwLockType) { } public void Read(byte[] pv, int cb, IntPtr pcbRead) { long bytes_read = base.Read(pv, 0, cb); if (pcbRead != IntPtr.Zero) Marshal.WriteInt64(pcbRead, bytes_read); } public void Revert() { } public void Seek(long dlibMove, int dwOrigin, IntPtr plibNewPosition) { long pos = base.Seek(dlibMove, (SeekOrigin)dwOrigin); if (plibNewPosition != IntPtr.Zero) Marshal.WriteInt64(plibNewPosition, pos); } public void SetSize(long libNewSize) { } public void Stat( out System.Runtime.InteropServices.ComTypes.STATSTG pstatstg, int grfStatFlag) { pstatstg = new System.Runtime.InteropServices.ComTypes.STATSTG(); pstatstg.cbSize = base.Length; } public void UnlockRegion(long libOffset, long cb, int dwLockType) { } public void Write(byte[] pv, int cb, IntPtr pcbWritten) { base.Write(pv, 0, cb); if (pcbWritten != IntPtr.Zero) Marshal.WriteInt64(pcbWritten, (long)cb); } #endregion }
C # use
IMemoryStream ms = new IMemoryStream(new byte[] { 0x45, 0x23, 0x67, 0x34 }); int size = LpTest.SizeOfLpStream(ms);