2009-09-21 19 views
5

Ich mache einige C# Interop Arbeit. Ich habe folgende Struktur:C#: Marshalling einer Struktur, die Arrays enthält

#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; 

Das ist mein Versuch ist es in eine C# struct zu konvertieren:

[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; 
} 

Jedes Mal, wenn ich initialisieren die Struktur der Name Device und Reservierte Felder sind alle gesetzt zu null. Wie behebe ich das?

Antwort

7

Für die Arrays, versuchen Sie den fixed Modifikator zu verwenden:

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

Dies funktioniert für die Arrays. Die korrekte Syntax ist jedoch öffentliches festes Byte DeviceInfo [MAX_LINK_DEVINFO]; Ich muss auch die Struktur als unsicher deklarieren. –

+0

Sie haben Recht, ich habe es –

3

wann immer ich die Struktur der Name Device initialisieren und Reservierte Felder sind alle auf null gesetzt

Das ist richtig, und Ihre Definition sieht für mich OK aus (BTW, Sie brauchen [MarshalAs] nicht für die primitiven Felder, das Standardverhalten ist das, was Sie dort angegeben haben). Da Ihre Array-Felder null sind, wird der Marshaller nichts dagegen tun, wenn Sie Ihre Struktur in nicht verwalteten Speicher migrieren, aber beim Abmarshalling werden die Strings und Arrays erstellt.

+1

anstelle von unsicheren und behoben, sollte der Code die Byte-Arrays zuweisen, bevor Sie es verwenden. Ich habe normalerweise einen Konstruktor in Strukturen für p/invoke, wo alle Arrays automatisch zugewiesen werden. – erict

0

Was Anton Tykhyy sagt, ist richtig. Ich möchte nur mit einigen Beispielen klären. Verwenden Sie "feste" Arbeiten, aber das zwingt Sie auch, "unsichere" zu verwenden. Ich möchte es vermeiden, wo immer möglich unsicher zu sein. Marschall zu benutzen, ist eine Möglichkeit, das zu umgehen.

Zuerst sagen wir, dass ich eine Bibliothek habe, die in C mit den folgenden Definitionen erstellt wurde.

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); 

In C#, würde die folgende Struktur der in C entsprechen

[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]; 
    } 
} 

Seit der msg in receiveMessage() wird als [out] dokumentiert, brauchen Sie nicht zu tun etwas Besonderes für das Array in der Struktur, bevor es an die Funktion übergeben wird. d.h .:

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

Da die msg in nachrichts() wird dokumentiert, wie [in], müssen Sie das Array füllen, bevor Sie die Funktion aufrufen. Bevor das Array gefüllt wird, muss das Array vor der Verwendung explizit instanziiert werden. d.h .:

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

Aufruf initializeArray() sollte das Array in dem vorher zugewiesenen Platz instanziiert innerhalb der Struktur für dieses Array erstellt.

Verwandte Themen