2014-09-23 2 views
0

ПомощьЭкспорт структура с 2 массива из C++ в C#

В C++

#pragma pack(push,1) 
typedef struct SIGMPGroup{ 
    int temp; 
    char name[50]; //name of group 
    int port; 
    char addr[50]; //network address "229." 
    //int ttl;   // 
    //int loop;   // 0 - no loop back, 1 - loop back 

    SIGMPGroup(): 
    temp(0), 
    port(0) 
    //ttl(-1), 
    //loop(0) 
    {} 
}; 
#pragma pack(pop) 

C#

public static SIGMPGroup DTIGMPGroup = new SIGMPGroup { temp = 56, name = "Example",port = 4000 }; 
    [StructLayout(LayoutKind.Explicit, Pack = 1, CharSet = CharSet.Ansi, Size = 108)] 
    public struct SIGMPGroup{ 
    [FieldOffset(0)] 
    public int temp; 
    [ FieldOffset(4), MarshalAs(UnmanagedType.ByValTStr,SizeConst=50)] 
    public string name; //name of group 
    [FieldOffset(54)] 
    public int port; 

    [FieldOffset(58), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] 
    public string addr; 

    } 

    [DllImport(Eth_DLL, CallingConvention = CallingConvention.Cdecl)] 
    public static extern void Leave(ref SIGMPGroup data); 

    ImportFunctionEth.Leave(ref ImportFunctionEth.DTIGMPGroup); 

После Run У меня есть ошибки: Не удалось загрузить тип "SIGMPGroup" из сборка «ConsoleApplication1, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null», потому что она содержит поле объекта со смещением 58, которое неправильно выровнено или перекрыто поле не представляют объект.

Если код

[FieldOffset(58), MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] 
public string addr; 

удаления, все работы. Зачем ?

Работа только как этот

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] 
    public struct SIGMPGroup{ 

    public int temp; 
    [ MarshalAs(UnmanagedType.ByValTStr,SizeConst=50)] 
    public string name; //name of group 

    public int port; 

    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] 
    public string addr; 

    } 
+0

Похоже, стандартное сортирование по неглавленной строке не допускается. Я объявлял бы единственный член byte [] в этой структуре с SizeConst = 108 и делал бы все вещи преобразования вручную, например, используя класс BitConverter, конструктор String (sbyte *) и т. Д. –

+0

, если использовать в качестве примера [FieldOffset (4), MarshalAs (UnmanagedType.ByValArray, SizeConst = 50)] public char [] name; У меня ошибка: не удалось упаковать тип, так как длина экземпляра встроенного массива не соответствует длине, объявленной в макете. – askeet

ответ

1

не уверен, что сделать из этой ошибки, CLR, кажется, хотят, чтобы сохранить STRUCT blittable по какой-то загадочной причине. Это, конечно, не так, струны портят это. В конечном счете ошибка вызвана полем , оно смещено, что нарушает обещание модели памяти .NET, что обновления для простых типов, такие как int, являются атомарными. Его смещение сдвигается до 56 и перекрывает вторую строку.

StructLayout.Explicit может быть причудливым, и вы очень помогаете. Просто решается, не помогая:

[StructLayout(LayoutKind.Sequential, Pack = 1, CharSet = CharSet.Ansi)] 
public struct SIGMPGroup { 
    public int temp; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] 
    public string name; //name of group 
    public int port; 
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 50)] 
    public string addr; 
} 

... 
Debug.Assert(Marshal.SizeOf(typeof(SIGMPGroup) == 108); // fine 
Смежные вопросы