Marshal.StructureToPtr InvalidCastException

时间:2012-07-06 15:14:45

标签: c#

在尝试将结构设置为指针时出现非常奇怪的错误...抛出了无效的强制转换异常并且我完全混淆了为什么。该函数要求3个参数,一个对象,IntPtr和一个布尔标志。我正在设置所有这些...甚至明确地将它们这样设置也没有区别。对象是一个结构,Intptr是一个指针并且有数据,而标志只是设置为false。

有人在之前的场景中收到过这个invalidcastexception吗?

修改

internal class FrameTransport
{
    #region Fields
    internal SharedMemoryChannel controlChannel;
    internal ControlChannelStruct controlStruct;
    internal SharedMemoryChannel frameChannel1;
    internal SharedMemoryChannel frameChannel2;
    internal byte[] bitmapData;
    internal int bitmapDataSize;
    internal uint sharedInfoSize;
    internal bool haveFrame;
    internal int height;
    internal int width;
    #endregion


    #region Structures
    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal struct FrameChannelStruct
    {
        public Int32 bufid;
        public Int32 size;
        public Int32 width;
        public Int32 height;
        public Int32 bitsperpixel;
        public Int32 fourcc;
        public Int32 orientation;
        public Int64 clientpointer;
    };

    [StructLayout(LayoutKind.Sequential, Pack = 1)]
    internal struct ControlChannelStruct
    {
        public Int32 bufferstates;
        public FrameChannelStruct buffer1;
        public FrameChannelStruct buffer2;
        public BufferType buftype;
        public Int32 configuration;
        public Int32 fourcccount;
        public Int32 fourcc01;
        public Int32 fourcc02;
        public Int32 fourcc03;
        public Int32 fourcc04;
        public Int32 fourcc05;
        public Int32 fourcc06;
        public Int32 fourcc07;
        public Int32 fourcc08;
        public Int32 fourcc09;
        public Int32 fourcc10;
    };
    #endregion


    #region Constructors
    /// <summary>
    /// Constructor.
    /// </summary>
    public FrameTransport()
    {
        sharedInfoSize = (uint)Marshal.SizeOf((Type)typeof(ControlChannelStruct));
        haveFrame = false;
        bitmapData = null;
        bitmapDataSize = 0;
        frameChannel1 = null;
        frameChannel2 = null;

        controlStruct = new ControlChannelStruct();
        controlStruct.bufferstates = 1;
        controlStruct.buffer1.bufid = -1;
        controlStruct.buffer2.bufid = -1;
        controlStruct.buffer1.clientpointer = 1;
        controlStruct.buffer2.clientpointer = 2;
        controlStruct.fourcccount = 0;
        controlStruct.buftype = BufferType.WINBUFFERS;

        controlChannel = new SharedMemoryChannel();
        bool success = controlChannel.CreateMapping(sharedInfoSize);

        if (!success)
        {
            throw new Exception("Unable to create memory mapping for video frame transport.");
        }

        controlChannel.OpenMapping(controlChannel.key);
        int error = Win32.GetLastError();

        if (error != 0)
        {
            throw new Exception("Unable to map memory for video frame transport.");
        }
    }
    #endregion


    #region Internal Members
    /// <summary>
    /// Send the control data.
    /// </summary>
    internal void SendControlData()
    {
        Marshal.StructureToPtr(controlStruct, controlChannel.data, false);
    }

    /// <summary>
    /// Get the control data.
    /// </summary>
    internal void GetControlData()
    {
        controlStruct.bufferstates = -1;
        controlStruct = (ControlChannelStruct)Marshal.PtrToStructure(controlChannel.data, typeof(ControlChannelStruct));
    }

    /// <summary>
    /// Communicate supported pixel formats to the runtime.
    /// </summary>
    /// <param name="count"></param>
    /// <param name="fourCcs"></param>
    internal void SetPreferences(int count, Int32[] fourCcs)
    {
        if (fourCcs.Length != 1)
        {
            throw new Exception("For now im assuming only one fourcc here.");
        }

        controlStruct.fourcccount = count;
        controlStruct.fourcc01 = fourCcs[0];
        controlStruct.fourcc02 = 0;
        controlStruct.fourcc03 = 0;
        controlStruct.fourcc04 = 0;
        controlStruct.fourcc05 = 0;
        controlStruct.fourcc06 = 0;
        controlStruct.fourcc07 = 0;
        controlStruct.fourcc08 = 0;
        controlStruct.fourcc09 = 0;
        controlStruct.fourcc10 = 0;

        SendControlData();
    }

    /// <summary>
    /// Get the buffer states.
    /// </summary>
    /// <returns></returns>
    internal int GetBufStates()
    {
        GetControlData();

        return controlStruct.bufferstates;
    }

    /// <summary>
    /// Return the channel's key.
    /// </summary>
    /// <returns></returns>
    internal uint Key()
    {
        return (uint)controlChannel.key;
    }

    /// <summary>
    /// Check if a new frame is available.
    /// </summary>
    /// <returns></returns>
    internal bool IsNewFrameAvailable()
    {
        GetControlData();
        int bufferState = (controlStruct.bufferstates & 0x3);

        if ((bufferState != 0x00) & (bufferState != 0x3))
        {
            return false;
        }

        return true;
    }

    /// <summary>
    /// Get the frame.
    /// </summary>
    /// <returns></returns>
    internal bool GetFrame()
    {
        int bufferState = (controlStruct.bufferstates & 0x03);

        if (!haveFrame & bufferState == 0x01) 
        { 
            return false; 
        }

        if (!haveFrame)
        {
            haveFrame = true;
        }

        if (bufferState == 0x00)
        {
            controlStruct.bufferstates |= 0x02;
        }

        if (bufferState == 0x03)
        {
            controlStruct.bufferstates &= ~0x02;
        }

        bufferState = (controlStruct.bufferstates & 0x03);

        FrameChannelStruct buffer;
        SharedMemoryChannel channel;

        if (bufferState == 0x1)
        {
            buffer = controlStruct.buffer1;
            channel = frameChannel1;
        }
        else if (bufferState == 0x2)
        {
            buffer = controlStruct.buffer2;
            channel = frameChannel2;
        }
        else
        {
            throw new Exception("Error: unexpected video control buffer state.");
        }

        if (channel == null)
        {
            channel = new SharedMemoryChannel();
            bool success = channel.OpenMapping(buffer.bufid);

            if (!success)
            {
                throw new Exception("Unable to map frame bitmap channel.");
            }
        };

        if (channel != null)
        {
            if (channel.key != buffer.bufid)
            {
                return false;
            };
        };

        width = buffer.width;
        height = buffer.height;
        int bytesPerPixel = buffer.bitsperpixel >> 3;
        int newFrameSize = width * height * bytesPerPixel;

        if (newFrameSize != bitmapDataSize)
        {
            bitmapData = null;
            bitmapDataSize = newFrameSize;
            bitmapData = new byte[bitmapDataSize];
        }

        Marshal.Copy(channel.data, bitmapData, 0, bitmapDataSize);

        if (bufferState == 0x1)
        {
            controlStruct.buffer1 = buffer;
            frameChannel1 = channel;
        }
        else if (bufferState == 0x2)
        {
            controlStruct.buffer2 = buffer;
            frameChannel2 = channel;
        }

        SendControlData();

        return true;
    }
    #endregion
}

1 个答案:

答案 0 :(得分:1)

结构中的BufferType必须是枚举,因为保存枚举值的自定义类型是缺陷。