2012-03-26 1 views
2

안전하지 않은 클래스에서 프로세스 간 통신을 위해 공유 메모리를 사용하고 있습니다. 메모리의 일부는 고정 된 int 배열을 보유하도록 예약되어 있습니다.안전하지 않은 C# : 기존 메모리 위치에 대한 포인터에서 int []를 어떻게 만들 수 있습니까?

기본적으로 공유 메모리를 설정하는 방법이 있습니다. 이런 식으로 뭔가 :

private int* sizePtr; 

private ???* arrayPtr; 

void SetupMemory(byte *pointerToSharedMem) 

{ 

    this.sizePtr = (int*)pointerToSharedMem; 
    pointerToSharedMem += sizeof(int); 

    this.arrayPtr = (???*)pointerToSharedMem; 
    pointerToSharedMem += sizeof(int) * FixedSizeOfArray; 
} 

내가

public int[] MyArray 
{ 
    get 
    { 
     return some magic with this.arrayPtr; 
    } 
} 

ETA 나는 속성을 사용할 수 있도록 포인터를 선언해야 할 방법 : 가능하면, 내가 구조체를 피하기 위해 싶습니다 나는 확실히 원하는 데이터 복사를 피하십시오. 데이터를 즉시 사용할 수 있도록 (즉, 복사하지 않고) 공유 메모리의 데이터에 대한 포인터를 사용하기 위해 어떤 종류의 캐스트 구조가 필요했습니다.

답변

0

포인터 여야합니까, 아니면 데이터를 복사 할 수 있습니까? 괜찮아요 경우

, 다음 위의 C# 2.0에서이 링크

http://msdn.microsoft.com/en-us/library/aa330463(v=vs.71).aspx

+0

포인터 여야합니다. 이 배열은 매우 자주 사용되며 데이터를 복사하는 것은 페널티가 너무 많습니다 (물론 다른 방법이 없다면). – Harald

0

을 확인하는 structunsafe 맥락에서, 내장 된 배열을 선언 할 수 있습니다 :

namespace FixedSizeBuffers 
{ 
    internal unsafe struct MyBuffer 
    { 
     public fixed int fixedBuffer[128]; 
    } 

    internal unsafe class MyClass 
    { 
     public MyBuffer myBuffer = default(MyBuffer); 
    } 

    internal class Program 
    { 
     static void Main() 
     { 
      MyClass myClass = new MyClass(); 

      unsafe 
      { 
       // Pin the buffer to a fixed location in memory. 
       fixed (int* intPtr = myClass.myBuffer.fixedBuffer) 
       { 
        *intPtr = someIntValue; 
       } 
      } 
     } 
    } 
} 

http://msdn.microsoft.com/en-us/library/zycewsya(v=vs.100).aspx

+0

구조체를 사용하지 않고 가능합니까? – Harald

+0

좋은 질문입니다. 아마도 그렇지 않다. C#에는 안전하지 않은 항목을 보관할 관리 컨테이너가 필요합니다. 관리 컨테이너이므로 관리 컨테이너는 문제없이 프로그램의 다른 곳에서 참조 할 수 있습니다. –

+0

코드를 제공해 주셔서 감사합니다. 그러나 귀하의 예제에서는 미리 선언 된 배열을 사용합니다. 필자의 예에서는 공유 메모리의 영역을 가리키는 포인터에서 배열을 파생해야합니다. – Harald

0

memcpy보다 나은 것을 생각할 수 없습니다.

[DllImport("msvcrt.dll", EntryPoint = "memcpy", CallingConvention = CallingConvention.Cdecl, SetLastError = false)] 
public static extern IntPtr memcpy(IntPtr dest, IntPtr src, UIntPtr count); 

private static unsafe int[] GetArray(int* ptr, uint length) 
{ 
    var ints = new int[length]; 

    fixed (int* pInts = ints) 
    { 
     memcpy(new IntPtr(pInts), new IntPtr(ptr), new UIntPtr(length)); 
    } 

    return ints; 
} 
3

사실 나는 다른 대답을 생각할 수 있습니다.

그래도 제대로 사용하지 않으면 추한 것일 수 있습니다.

주의하십시오!

public unsafe class UnsafeArray 
{ 
    private readonly int* _start; 
    public readonly int Length; 

    public UnsafeArray(int* start, int enforceLength = 0) 
    { 
     this._start = start; 
     this.Length = enforceLength > 0 ? enforceLength : int.MaxValue; 
    } 

    public int this[int index] 
    { 
     get { return _start[index]; } 
     set 
     { 
      if (index >= this.Length) 
      { 
       throw new IndexOutOfRangeException(); 
      } 

      _start[index] = value; 
     } 
    } 
} 
+0

이 답변에 영감을 받았습니다. - 감사합니다! - 매개 변수로 인덱스가있는 Set 및 Get 메서드를 사용하기 만합니다. 그것은 내가 바라는만큼 좋은 솔루션은 아니지만 꽤 직관적이며 데이터를 복사하지 않고 트릭을 수행합니다. – Harald

+1

다행입니다. 인덱서를 유지하면 Get 및 Set 메서드 역할을하고 글쓰기를 저장하여 배열처럼 보이게합니다. – SimpleVar