2012-08-15 3 views
4

pinvoke를 사용하여 C에서 C로 다른 구조체 내의 구조체 배열을 마샬링하려고합니다. AFAIK, 안돼.
대신 C 구조체에서 ptr을 my 배열과 malloc으로 선언합니다. 문제점 : 1) C# 측에서 동등한 것을 어떻게 선언합니까? 2) 어떻게하면 C# 측에 해당하는 것을 할당하고 사용할 수 있습니까?C 배열 포인터를 C로 사용하는 방법 #

//The C code 
typedef struct { 
     int a; 
     int b; } A; 
typedef struct { 
     int c; 
     // A myStruct[100]; // can't do this, so: 
     A *myStruct; } B; 

//The c# code: 
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public class A{ 
    int a; 
    int b; 
} 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public class B{ 
     int c; 
     // can't declare array of [100] A structures... 
    ? 
} 

[편집] 어떤 식 으로든 저는 다른 곳에서 C# 측의 객체 고정 배열에 대해 읽은 것을 잘못 해석했습니다.

data.B[3].a = 4567;을 그래서이 오류가 무엇인지에 대해 다른 곳에서 읽기 : 사용하는 경우 그리고 C에서 배열 크기 그래서 확인 컴파일 문제를 해결할 수 있습니다,하지만 난 "개체 참조가 개체의 인스턴스로 설정되지 않았습니다"수 , 나는이 방법을 추가했다.

public void initA() 
     { 
      for (int i = 0; i < 100; i++) { B[i] = new A(); } 
     } 

다시 컴파일했지만 OK이지만 동일한 오류 메시지.

+0

'A [] myStruct'을 사용해 보셨나요? –

+0

괜찮습니다. 하지만 어떻게 스토리지를 할당하고 사용합니까 (여전히 C#을 배우고 있습니다). 감사. – PaeneInsula

+0

그냥 궁금 해서요 : 왜 * C에서'myStruct [100];을 사용할 수 없습니까? 그것은 C# 측의 작업을 훨씬 쉽게 만듭니다. –

답변

5

C와 C# 사이에 이와 같은 "복잡한"구조를 마샬링하려면 두 가지 옵션이 있습니다.

이 경우에는 고정 배열을 C 측 구조에 포함 시키십시오. C# 측을 많이 단순화 할 것이므로이 배열을 사용하는 것이 좋습니다.

// In C: 
typedef struct 
{ 
int a; 
int b; 
} A; 

typedef struct 
{ 
int c; 
A data[100]; 
} B; 

// In C#: 
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct A 
{ 
    int a; 
    int b; 
} 

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 
public struct B 
{ 
    int c; 
    [MarshalAs(UnmanagedType.LPArray, SizeConst=100)] 
    A[] data = new data[100]; 
} 

당신이 모르는, 또는 배열, 고정 된 크기를 지정할 수없는 경우 당신은 런타임에 배열에 할당 할 필요가 C#을 얼마나 많은 공간을 이야기하는 MarshalAs 속성을 사용할 수 있습니다 , 당신은 당신이 한 일을하고 C의 포인터로 선언 할 필요가있을 것이다.이 경우, 배열이 런타임에 얼마나 많은 메모리를 사용할지를 알 수 없으므로, 꽤 많이 붙어있다. 손으로 모든 마샬링을하고 있습니다. This question 작동하는 방법의 좋은 개요를 가지고 있지만, 기본적인 아이디어는 : 당신은 배열 요소의 수를 포함하여 구조에 필드를 추가해야합니다

  1. (이 훨씬 더 쉽게 당신의 인생을 만들 것입니다) C#의 필드를 속성이없는 IntPtr data;으로 선언하십시오.
  2. Marshal.SizeOf(typeof(A))을 사용하여 관리되지 않는 메모리의 구조체 크기를 가져옵니다.
  3. 사용 Marshal.PtrToStructure는 당신이 밖으로 실행할 때까지 배열
  4. 루프의 다음 구조를 이동하는 데 사용할 IntPtr.Add(ptr, sizeofA) C#
  5. 단일 관리되지 않는 구조를 변환합니다.
+0

객체 참조가 objec의 인스턴스로 설정되지 않았습니다 – PaeneInsula

+0

오류 메시지 수정 방법에 대한 위의 편집을 참조하십시오. – PaeneInsula

+0

배열이 참조 유형이므로 C# 크기에서는 여전히 필드에 배열을 할당해야합니다. 당신은이 인라인을 할 수 있어야합니다, 나는 내 대답을 편집했습니다. –

관련 문제