문제

I've seen several related topics on SO and other forums, but haven't found a workable answer to my question.

Here's my code:

[StructLayout(LayoutKind.Explicit, Size = 128)]
internal unsafe struct Frame
{
    [FieldOffset(0)]
    public fixed byte Bytes[128];

    [FieldOffset(0)]
    public long Low;

    [FieldOffset(128 - sizeof(long))]
    public long High;
}

unsafe private void button32_Click(object sender, EventArgs e)
{
    Frame frame;

    // ERROR: Error 15  You cannot use the fixed statement to take the address of an already fixed expression
    fixed (byte* ptr = frame.Bytes)
    {

    }

    // ERROR
    Console.Write(System.Text.Encoding.ASCII.GetString(frame.Bytes, 0, 128));
    frame.Low = 1234;
    //Console.Write(System.Text.Encoding.ASCII.GetString(frame.Bytes));
    frame.High = 5678;
    //Console.Write(System.Text.Encoding.ASCII.GetString(frame.Bytes));
}
도움이 되었습니까?

해결책

Just wrap the struct into another class to eliminate the fixed pointer issue. This creates the struct inside the memory frame of the new class. Then convert the fixed array to a byte[] to eliminate the GetString() issue. Maybe this helps?

namespace test
{
        [StructLayout(LayoutKind.Explicit, Size = 128)]
        internal unsafe struct Frame
        {
            [FieldOffset(0)]
            public fixed byte Bytes[128];

            [FieldOffset(0)]
            public long Low;

            [FieldOffset(128 - sizeof(long))]
            public long High;                
        }

    internal class NewClass
    {
        public Frame FixedBytesArray;
    }

    internal class Program
    {
        static void Main(string[] args)
        {
            unsafe
            {
                NewClass NewType = new NewClass();
                NewType.FixedBytesArray.High = 12345;
                NewType.FixedBytesArray.Low = 6789;


                fixed (byte* ptr = NewType.FixedBytesArray.Bytes)
                {
                    byte[] bytes = new byte[128];
                    int index = 0;
                    for (byte* counter = ptr; *counter != 0; counter++)
                    {
                        bytes[index++] = *counter;
                    }

                    Console.Write(System.Text.Encoding.ASCII.GetString(bytes, 0, 128));
                }
            }    
        }
    }
}

다른 팁

static byte[] GetBytes(string str)
{
    byte[] bytes = new byte[str.Length * sizeof(char)];
    System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
    return bytes;
}

static string GetString(byte[] bytes)
{
    char[] chars = new char[bytes.Length / sizeof(char)];
    System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
    return new string(chars);
}


static byte[] StringToByteArray(string str, int length) 
{
    return Encoding.ASCII.GetBytes(str.PadRight(length, ' '));
}  

Nothing of the above works for me, so I created another solution:

StringBuilder sb = new StringBuilder();
fixed (byte* b = fixedByteArray)
{
  for (int i = 0; i < knownLengthOfByteArray; i++)
  {
    sb.Append((char)b[i]);
  }
}
return sb.ToString();

Works for ANSI strings.

The compiler error states it very well: you were trying to fix something that already has been fixed...

You only fix the reference when assigning a pointer. This prevents the reference to be moved to somewhere else in memory (garbage collection) then expected - using MS words, the reference becomes 'pinned'.

In your case, you don't need to fix your struct when defining but when referencing your pointer fix the 'source' by applying the "fixed" statement (this part of your code is correct).

Solution should be to remove the fix statements from your struct. If you like to read some about it: MSDN - fixed Statement (C# Reference)

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top