2009-09-21 4 views
5

일부 C# interop 작업을 수행하고 있습니다. 이것은 C#을 구조체로 변환하는 나의 시도배열을 포함하는 구조체를 마샬링 C# :

#pragma pack(push,1) 
typedef struct 
{ 
    unsigned __int64 Handle; 
    LinkType_t Type; 
    LinkState_t State; 
    unsigned __int64 Settings; 
    signed __int8 Name[MAX_LINK_NAME]; 
    unsigned __int8 DeviceInfo[MAX_LINK_DEVINFO]; 
    unsigned __int8 Reserved[40]; 
} LinkInfo_t; 

: 나는 다음과 같은 구조체가 그러나

[StructLayout(LayoutKind.Sequential, Pack = 1)] 
public struct LinkInfo_t 
{ 
    [MarshalAs(UnmanagedType.U8)] 
    public UInt64 Handle; 
    MarshalAs(UnmanagedType.I4)] 
    public LinkType_t Type; 
    [MarshalAs(UnmanagedType.I4)] 
    public LinkState_t State; 
    [MarshalAs(UnmanagedType.U8)] 
    public UInt64 Settings; 
    [MarshalAs(UnmanagedType.LPStr, SizeConst = MAX_LINK_NAME)] 
    public string Name; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = MAX_LINK_DEVINFO, ArraySubType = UnmanagedType.U1)] 
    public byte[] DeviceInfo; 
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 40, ArraySubType = UnmanagedType.U1)] 
    public byte[] Reserved; 
} 

를, 내가 구조체 이름, DeviceInfo를 초기화하고 예약 필드는 모든 설정 때마다 null로. 이 문제를 어떻게 해결할 수 있습니까?

답변

7

배열의 경우, fixed 수정 사용하려고 : 나는 구조체 이름, DeviceInfo를 초기화 할 때마다

public fixed byte DeviceInfo[MAX_LINK_DEVINFO]; 
    public fixed byte Reserved[40]; 
+0

배열에 대해 작동합니다. 그러나 올바른 구문은 공용 고정 바이트 DeviceInfo [MAX_LINK_DEVINFO]입니다. 또한 구조체를 안전하지 않은 것으로 선언해야합니다. –

+0

맞습니다. 안전하지 않고 고정 된 대신 –

3

을하고, 예약 필드는 모두 null로 설정됩니다

이것은 맞고, 당신의 정의는 나에게 잘 보입니다. (BTW, 당신은 기본 필드에 [MarshalAs]이 필요하지 않습니다. 기본 동작은 거기에 지정한 것을하는 것입니다). 배열 필드가 null이기 때문에 마샬 러는 구조체를 관리되지 않는 메모리에 마샬링 할 때 아무 것도 수행하지 않지만 언 마샬링 할 때 문자열과 배열을 만들 것입니다.

+1

으로 고정 시켰습니다. 코드는 사용하기 전에 바이트 배열을 할당해야합니다. 나는 일반적으로 어떤 배열이 자동으로 할당되는 p/invoke 구조체에 대한 생성자를 가지고있다. – erict

0

Anton Tykhyy의 말은 정확합니다. 나는 단지 몇 가지 예제로 명확히하고 싶다. '고정 된'작품을 사용하지만 그뿐만 아니라 '안전하지 않은'을 사용하도록 강요합니다. 나는 가능한 한 안전하지 않은 것을 사용하고 싶지 않다. 마셜을 사용하는 것은 그것을 해결하는 방법입니다.

먼저, 다음 정의를 사용하여 C로 작성된 라이브러리가 있다고 가정 해 보겠습니다. C#으로

typedef struct { 
    int messageType; 
    BYTE payload[60]; 
} my_message; 

/** 
* \param[out] msg Where the message will be written to 
*/ 
void receiveMessage(my_message *msg); 

/* 
* \param[in] msg The message that will be sent 
*/ 
void sendMessage(my_message *msg); 

다음 구조) receiveMessage (의 MSG 이후 C.

[StructLayout(LayoutKind.Sequential, Size = 64), Serializable] 
struct my_message 
{ 
    int messageType; 
    [MarshalAs(UnmanagedType.ByValArray,SizeConst = 60)] 
    byte[] payload; 

    public initializeArray() 
    { 
     //explicitly initialize the array 
     payload = new byte[60]; 
    } 
} 

의 하나에 해당 할 것이다 [아웃, 당신이 필요하지 않는 문서화 함수에 전달하기 전에 구조체의 배열에 특별한 요소. 즉 : sendMessage 첨부에서 MSG는()에서] 문서화되어 있으므로

my_message msg = new my_message(); 
receiveMessage(ref msg); 
byte payload10 = msg.payload[10]; 

에는 함수를 호출하기 전에 어레이를 작성해야한다. 배열을 채우기 전에 배열을 사용하기 전에 명시 적으로 인스턴스화해야합니다. 즉 :

my_message msg = new my_message(); 
msg.initializeArray(); 
msg.payload[10] = 255; 
sendMessage(ref msg); 

initializeArray()를 호출하면이 배열의 구조체 내에 만들어진 이전에 할당 된 공간에서 배열을 인스턴스화해야합니다.

관련 문제