你无法通过CLI传递Memorystream
。你能做的最好的事情就是传递一个指向字节缓冲区的“指针”(IntPtr)。
更多详细信息请参见如何使用P/Invoke将MemoryStream数据传递给非托管C++ DLL?
我能够根据这个帖子 (PInvoke和IStream) 得到一个示例。基本上,您需要在C#中实现IStream接口。然后,您可以将自定义的MemoryStream
作为LPSTREAM
传递到C++端。以下是一个代码示例,它获取流并获取大小(只是一个简单的示例,以显示如何完成):
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"
[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定义
[DllImport("LpWin32Dll.dll", CallingConvention=CallingConvention.StdCall)]
public static extern int SizeOfLpStream(IStream iStream)
C# IStream实现(必须实现IStream接口)。我刚刚为MemoryStream
类创建了一个包装类。
[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# 使用
IMemoryStream ms = new IMemoryStream(new byte[] { 0x45, 0x23, 0x67, 0x34 });
int size = LpTest.SizeOfLpStream(ms);