2009-07-19 14 views
2

내가 원하는 관리되지 않는 구조체는 다음과 같이 기본적으로 보이는 날카로운 C의 마샬링해야 :
어떻게 재귀 구조체를 C 샤시로 마샬링합니까?

struct MyStruct{ 
    /* ... some stuff ... */ 
    int numChilds; 
    MyStruct *childs; 
} 

나는 사용자 지정 마샬 러를 쓸 필요가 있다고 생각하지만 진행 방법에 대한 확실하지 않다 .

답변

3

는 내가 직접 인덱스 아이들이 필요하지 않는 경우이 같은 설정을 사용하려면 방법 GetChild (아래 그림 참조). 더 어려운 방법은 IList<MyStruct>을 구현하는 도우미/래퍼 클래스를 만드는 것입니다. 인스턴스는 Children 속성에서 반환되며 내부는 GetChild 메서드를 호출하여 작동합니다. 이것은 필요한 경우 독자에게 연습으로 남겨 둡니다.

public MyStruct GetChild(int index) 
{ 
    if (index < 0) 
     throw new ArgumentOutOfRangeException("index", "The index must be >= 0."); 
    if (index >= this.numChilds) 
     throw new ArgumentException("The index must be less than the number of children", "index"); 

    int elementSize = Marshal.SizeOf(typeof(MyStruct)); 
    IntPtr data = new IntPtr(childData.ToInt64() + elementSize * index); 
    MyStruct child = (MyStruct)Marshal.PtrToStructure(data, typeof(MyStruct)); 
    return child; 
} 
0

일부 관리되지 않는 함수에 전달하려는 경우 안전하지 않은 코드와 stackalloc/배열을 수정하여 개체 배열에 대한 포인터를 얻을 수 있습니다. 당신이 경우

struct MyStruct 
{ 
    /* ... some stuff ... */ 
    int numChilds; 
    IntPtr childData; 

    public IEnumerable<MyStruct> Children 
    { 
     get 
     { 
      int elementSize = Marshal.SizeOf(typeof(MyStruct)); 
      for (int i = 0; i < this.numChilds; i++) 
      { 
       IntPtr data = new IntPtr(this.childData.ToInt64() + elementSize * i); 
       MyStruct child = (MyStruct)Marshal.PtrToStructure(data, typeof(MyStruct)); 
       yield return child; 
      } 
     } 
    } 
} 

직접 인덱스 아이들이 쉬운 일이를 만드는해야

 unsafe struct Foo 
     { 
      public int value; 
      public int fooCount; 
      public Foo* foos; 
     } 

     [DllImport("dll_natv.dll")] 
     static extern void PrintFoos(Foo f); 

     public unsafe static void Main() 
     { 
      Foo* foos = stackalloc Foo[10]; 

      for (int i = 0; i < 10; ++i) 
       foos[i].value = i; 

      Foo mainFoo = new Foo(); 
      mainFoo.fooCount = 10; 
      mainFoo.value = 100; 
      mainFoo.foos = foos; 

      PrintFoos(mainFoo); 


     }