.NET 相当于 Delphi IStream 初始化

发布于 2024-09-28 19:05:14 字数 451 浏览 4 评论 0原文

我有以下 Delphi 代码:

var
 Stream: TMemoryStream;
 StreamI: TStreamAdapter;
 OleStream: IStream;
begin

 Stream:= TMemoryStream.Create;
 Stream.LoadFromFile(filename);
 StreamI:= TStreamAdapter.Create(Stream, soOwned);
 VSPDFViewer1.LoadStream(StreamI as IStream, '');
end;

它实际上将 IStream 对象传递给 COM 组件。 .NET 有“System.Runtime.InteropServices.ComTypes.IStream”接口,但我无法找到使用它的正确方法。如何使用数据初始化 IStream 并将其传递给 .NET 中的 COM 对象?

I have the following Delphi code:

var
 Stream: TMemoryStream;
 StreamI: TStreamAdapter;
 OleStream: IStream;
begin

 Stream:= TMemoryStream.Create;
 Stream.LoadFromFile(filename);
 StreamI:= TStreamAdapter.Create(Stream, soOwned);
 VSPDFViewer1.LoadStream(StreamI as IStream, '');
end;

Which actually passes an IStream object to a COM component.
.NET has the "System.Runtime.InteropServices.ComTypes.IStream" interface, but I can't figure out a proper way to use it. How to initialize IStream with data and pass it to COM object in .NET?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

徒留西风 2024-10-05 19:05:14

这有点糟糕,但您必须编写自己的 .NET StreamAdapter 类。幸运的是,您可以从 Microsoft 窃取所有代码:

public class StreamAdapter : System.Runtime.InteropServices.ComTypes.IStream
{
    // Fields
    protected Stream dataStream;
    private long virtualPosition = -1L;

    // Methods
    internal StreamAdapter(Stream stream)
    {
        if (!stream.CanSeek)
        {
            int num;
            byte[] sourceArray = new byte[0x100];
            int offset = 0;
            do
            {
                if (sourceArray.Length < (offset + 0x100))
                {
                    byte[] destinationArray = new byte[sourceArray.Length * 2];
                    Array.Copy(sourceArray, destinationArray, sourceArray.Length);
                    sourceArray = destinationArray;
                }
                num = stream.Read(sourceArray, offset, 0x100);
                offset += num;
            }
            while (num != 0);
            this.dataStream = new MemoryStream(sourceArray);
        }
        else
        {
            this.dataStream = stream;
        }
    }

    private void ActualizeVirtualPosition()
    {
        if (this.virtualPosition != -1L)
        {
            if (this.virtualPosition > this.dataStream.Length)
            {
                this.dataStream.SetLength(this.virtualPosition);
            }
            this.dataStream.Position = this.virtualPosition;
            this.virtualPosition = -1L;
        }
    }

    public virtual System.Runtime.InteropServices.ComTypes.IStream Clone()
    {
        NotImplemented();
        return null;
    }

    public virtual void Commit(int grfCommitFlags)
    {
        this.dataStream.Flush();
        this.ActualizeVirtualPosition();
    }

    [SecurityPermission(SecurityAction.Assert, Flags=SecurityPermissionFlag.UnmanagedCode), UIPermission(SecurityAction.Demand, Window=UIPermissionWindow.AllWindows)]
    public virtual long CopyTo(UnsafeNativeMethods.IStream pstm, long cb, long[] pcbRead)
    {
        int num = 0x1000;
        IntPtr buf = Marshal.AllocHGlobal(num);
        if (buf == IntPtr.Zero)
        {
            throw new OutOfMemoryException();
        }
        long num2 = 0L;
        try
        {
            while (num2 < cb)
            {
                int length = num;
                if ((num2 + length) > cb)
                {
                    length = (int) (cb - num2);
                }
                int len = this.Read(buf, length);
                if (len == 0)
                {
                    goto Label_006C;
                }
                if (pstm.Write(buf, len) != len)
                {
                    throw EFail("Wrote an incorrect number of bytes");
                }
                num2 += len;
            }
        }
        finally
        {
            Marshal.FreeHGlobal(buf);
        }
    Label_006C:
        if ((pcbRead != null) && (pcbRead.Length > 0))
        {
            pcbRead[0] = num2;
        }
        return num2;
    }

    protected static ExternalException EFail(string msg)
    {
        throw new ExternalException(msg, -2147467259);
    }

    public virtual Stream GetDataStream()
    {
        return this.dataStream;
    }

    public virtual void LockRegion(long libOffset, long cb, int dwLockType)
    {
    }

    protected static void NotImplemented()
    {
        throw new ExternalException(SR.GetString("NotImplemented"), -2147467263);
    }

    public virtual int Read(IntPtr buf, int length)
    {
        byte[] buffer = new byte[length];
        int num = this.Read(buffer, length);
        Marshal.Copy(buffer, 0, buf, length);
        return num;
    }

    public virtual int Read(byte[] buffer, int length)
    {
        this.ActualizeVirtualPosition();
        return this.dataStream.Read(buffer, 0, length);
    }

    public virtual void Revert()
    {
        NotImplemented();
    }

    public virtual long Seek(long offset, int origin)
    {
        long virtualPosition = this.virtualPosition;
        if (this.virtualPosition == -1L)
        {
            virtualPosition = this.dataStream.Position;
        }
        long length = this.dataStream.Length;
        switch (origin)
        {
            case 0:
                if (offset > length)
                {
                    this.virtualPosition = offset;
                    break;
                }
                this.dataStream.Position = offset;
                this.virtualPosition = -1L;
                break;

            case 1:
                if ((offset + virtualPosition) > length)
                {
                    this.virtualPosition = offset + virtualPosition;
                    break;
                }
                this.dataStream.Position = virtualPosition + offset;
                this.virtualPosition = -1L;
                break;

            case 2:
                if (offset > 0L)
                {
                    this.virtualPosition = length + offset;
                    break;
                }
                this.dataStream.Position = length + offset;
                this.virtualPosition = -1L;
                break;
        }
        if (this.virtualPosition != -1L)
        {
            return this.virtualPosition;
        }
        return this.dataStream.Position;
    }

    public virtual void SetSize(long value)
    {
        this.dataStream.SetLength(value);
    }

    public void Stat(IntPtr pstatstg, int grfStatFlag)
    {
        STATSTG structure = new STATSTG();
        structure.cbSize = this.dataStream.Length;
        Marshal.StructureToPtr(structure, pstatstg, true);
    }

    public virtual void UnlockRegion(long libOffset, long cb, int dwLockType)
    {
    }

    public virtual int Write(IntPtr buf, int length)
    {
        byte[] destination = new byte[length];
        Marshal.Copy(buf, destination, 0, length);
        return this.Write(destination, length);
    }

    public virtual int Write(byte[] buffer, int length)
    {
        this.ActualizeVirtualPosition();
        this.dataStream.Write(buffer, 0, length);
        return length;
    }

    // Nested Types
    [StructLayout(LayoutKind.Sequential)]
    public class STATSTG
    {
        public IntPtr pwcsName = IntPtr.Zero;
        public int type;
        [MarshalAs(UnmanagedType.I8)]
        public long cbSize;
        [MarshalAs(UnmanagedType.I8)]
        public long mtime;
        [MarshalAs(UnmanagedType.I8)]
        public long ctime;
        [MarshalAs(UnmanagedType.I8)]
        public long atime;
        [MarshalAs(UnmanagedType.I4)]
        public int grfMode;
        [MarshalAs(UnmanagedType.I4)]
        public int grfLocksSupported;
        public int clsid_data1;
        [MarshalAs(UnmanagedType.I2)]
        public short clsid_data2;
        [MarshalAs(UnmanagedType.I2)]
        public short clsid_data3;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b0;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b1;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b2;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b3;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b4;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b5;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b6;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b7;
        [MarshalAs(UnmanagedType.I4)]
        public int grfStateBits;
        [MarshalAs(UnmanagedType.I4)]
        public int reserved;
    }
}

It kind of sucks, but you're going to have to write your own .NET StreamAdapter class. Fortunately you can steal all the code from Microsoft:

public class StreamAdapter : System.Runtime.InteropServices.ComTypes.IStream
{
    // Fields
    protected Stream dataStream;
    private long virtualPosition = -1L;

    // Methods
    internal StreamAdapter(Stream stream)
    {
        if (!stream.CanSeek)
        {
            int num;
            byte[] sourceArray = new byte[0x100];
            int offset = 0;
            do
            {
                if (sourceArray.Length < (offset + 0x100))
                {
                    byte[] destinationArray = new byte[sourceArray.Length * 2];
                    Array.Copy(sourceArray, destinationArray, sourceArray.Length);
                    sourceArray = destinationArray;
                }
                num = stream.Read(sourceArray, offset, 0x100);
                offset += num;
            }
            while (num != 0);
            this.dataStream = new MemoryStream(sourceArray);
        }
        else
        {
            this.dataStream = stream;
        }
    }

    private void ActualizeVirtualPosition()
    {
        if (this.virtualPosition != -1L)
        {
            if (this.virtualPosition > this.dataStream.Length)
            {
                this.dataStream.SetLength(this.virtualPosition);
            }
            this.dataStream.Position = this.virtualPosition;
            this.virtualPosition = -1L;
        }
    }

    public virtual System.Runtime.InteropServices.ComTypes.IStream Clone()
    {
        NotImplemented();
        return null;
    }

    public virtual void Commit(int grfCommitFlags)
    {
        this.dataStream.Flush();
        this.ActualizeVirtualPosition();
    }

    [SecurityPermission(SecurityAction.Assert, Flags=SecurityPermissionFlag.UnmanagedCode), UIPermission(SecurityAction.Demand, Window=UIPermissionWindow.AllWindows)]
    public virtual long CopyTo(UnsafeNativeMethods.IStream pstm, long cb, long[] pcbRead)
    {
        int num = 0x1000;
        IntPtr buf = Marshal.AllocHGlobal(num);
        if (buf == IntPtr.Zero)
        {
            throw new OutOfMemoryException();
        }
        long num2 = 0L;
        try
        {
            while (num2 < cb)
            {
                int length = num;
                if ((num2 + length) > cb)
                {
                    length = (int) (cb - num2);
                }
                int len = this.Read(buf, length);
                if (len == 0)
                {
                    goto Label_006C;
                }
                if (pstm.Write(buf, len) != len)
                {
                    throw EFail("Wrote an incorrect number of bytes");
                }
                num2 += len;
            }
        }
        finally
        {
            Marshal.FreeHGlobal(buf);
        }
    Label_006C:
        if ((pcbRead != null) && (pcbRead.Length > 0))
        {
            pcbRead[0] = num2;
        }
        return num2;
    }

    protected static ExternalException EFail(string msg)
    {
        throw new ExternalException(msg, -2147467259);
    }

    public virtual Stream GetDataStream()
    {
        return this.dataStream;
    }

    public virtual void LockRegion(long libOffset, long cb, int dwLockType)
    {
    }

    protected static void NotImplemented()
    {
        throw new ExternalException(SR.GetString("NotImplemented"), -2147467263);
    }

    public virtual int Read(IntPtr buf, int length)
    {
        byte[] buffer = new byte[length];
        int num = this.Read(buffer, length);
        Marshal.Copy(buffer, 0, buf, length);
        return num;
    }

    public virtual int Read(byte[] buffer, int length)
    {
        this.ActualizeVirtualPosition();
        return this.dataStream.Read(buffer, 0, length);
    }

    public virtual void Revert()
    {
        NotImplemented();
    }

    public virtual long Seek(long offset, int origin)
    {
        long virtualPosition = this.virtualPosition;
        if (this.virtualPosition == -1L)
        {
            virtualPosition = this.dataStream.Position;
        }
        long length = this.dataStream.Length;
        switch (origin)
        {
            case 0:
                if (offset > length)
                {
                    this.virtualPosition = offset;
                    break;
                }
                this.dataStream.Position = offset;
                this.virtualPosition = -1L;
                break;

            case 1:
                if ((offset + virtualPosition) > length)
                {
                    this.virtualPosition = offset + virtualPosition;
                    break;
                }
                this.dataStream.Position = virtualPosition + offset;
                this.virtualPosition = -1L;
                break;

            case 2:
                if (offset > 0L)
                {
                    this.virtualPosition = length + offset;
                    break;
                }
                this.dataStream.Position = length + offset;
                this.virtualPosition = -1L;
                break;
        }
        if (this.virtualPosition != -1L)
        {
            return this.virtualPosition;
        }
        return this.dataStream.Position;
    }

    public virtual void SetSize(long value)
    {
        this.dataStream.SetLength(value);
    }

    public void Stat(IntPtr pstatstg, int grfStatFlag)
    {
        STATSTG structure = new STATSTG();
        structure.cbSize = this.dataStream.Length;
        Marshal.StructureToPtr(structure, pstatstg, true);
    }

    public virtual void UnlockRegion(long libOffset, long cb, int dwLockType)
    {
    }

    public virtual int Write(IntPtr buf, int length)
    {
        byte[] destination = new byte[length];
        Marshal.Copy(buf, destination, 0, length);
        return this.Write(destination, length);
    }

    public virtual int Write(byte[] buffer, int length)
    {
        this.ActualizeVirtualPosition();
        this.dataStream.Write(buffer, 0, length);
        return length;
    }

    // Nested Types
    [StructLayout(LayoutKind.Sequential)]
    public class STATSTG
    {
        public IntPtr pwcsName = IntPtr.Zero;
        public int type;
        [MarshalAs(UnmanagedType.I8)]
        public long cbSize;
        [MarshalAs(UnmanagedType.I8)]
        public long mtime;
        [MarshalAs(UnmanagedType.I8)]
        public long ctime;
        [MarshalAs(UnmanagedType.I8)]
        public long atime;
        [MarshalAs(UnmanagedType.I4)]
        public int grfMode;
        [MarshalAs(UnmanagedType.I4)]
        public int grfLocksSupported;
        public int clsid_data1;
        [MarshalAs(UnmanagedType.I2)]
        public short clsid_data2;
        [MarshalAs(UnmanagedType.I2)]
        public short clsid_data3;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b0;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b1;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b2;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b3;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b4;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b5;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b6;
        [MarshalAs(UnmanagedType.U1)]
        public byte clsid_b7;
        [MarshalAs(UnmanagedType.I4)]
        public int grfStateBits;
        [MarshalAs(UnmanagedType.I4)]
        public int reserved;
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文