Marshal C ++ struct array i C #

stemmer
26

Jeg har følgende struct i C ++:

#define MAXCHARS 15

typedef struct 
{
    char data[MAXCHARS];
    int prob[MAXCHARS];
} LPRData;

Og en funksjon som jeg p / påkalle inn for å få en rekke tre av disse strukturene:

void GetData(LPRData *data);

I C ++ ville jeg bare gjøre noe som dette:

LPRData *Results;
Results = (LPRData *)malloc(MAXRESULTS*sizeof(LPRData));
GetData( Results );

Og det ville fungere helt fint, men i C # Jeg kan ikke synes å få det til å fungere. Jeg har opprettet en C # struct som dette:

public struct LPRData
{

    /// char[15]
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
    public string data;

    /// int[15]
    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)]
    public int[] prob;
}

Og hvis jeg initialisere en rekke tre av dem (og alle deres under arrays) og gi det til dette:

GetData(LPRData[] data);

Den returnerer med suksess, men dataene i LPRData matrisen er ikke endret.

Jeg har selv forsøkt å skape en rå byte array størrelsen på 3 LPRData og passerer det inn en funksjon prototype som dette:

GetData (byte [] data);

Men i så fall vil jeg få data streng fra første LPRData struktur, men ingenting etter det, inkludert prob array fra samme LPRData.

Noen ideer om hvordan du skal håndtere dette?

Publisert på 09/10/2008 klokken 17:27
kilden bruker
På andre språk...                            


5 svar

stemmer
24

Jeg vil prøve å legge noen attributter til din struct decloration

[StructLayout(LayoutKind.Sequential, Size=TotalBytesInStruct),Serializable]
public struct LPRData
{
/// char[15]
[MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
public string data;

/// int[15]
[MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)]
public int[] prob;
}

* Merk TotalBytesInStruct ikke er ment å representere en variabel

JaredPar er også riktig at du bruker IntPtr klassen kan være nyttig, men det har vært en god stund siden jeg har brukt PInvoke så jeg er rusten.

Svarte 09/10/2008 kl. 17:54
kilden bruker

stemmer
13

Et triks når du arbeider med pekere er å bare bruke en IntPtr. Du kan deretter bruke Marshal.PtrToStructure på pekeren og tilvekst basert på størrelsen av strukturen for å få resultater.

static extern void GetData([Out] out IntPtr ptr);

LPRData[] GetData()
{
    IntPtr value;
    LPRData[] array = new LPRData[3];
    GetData(out value);
    for (int i = 0; i < array.Length; i++)
    {
        array[i] = Marshal.PtrToStructure(value, typeof(LPRData));
        value += Marshal.SizeOf(typeof(LPRData));
    }
    return array;
}
Svarte 09/10/2008 kl. 17:50
kilden bruker

stemmer
3

Den PInvoke Interop Assistant kan hjelpe. http://clrinterop.codeplex.com/releases/view/14120

Svarte 16/10/2008 kl. 02:37
kilden bruker

stemmer
2

En lignende tema ble diskutert på dette spørsmålet , og en av konklusjonene var at CharSetheter parameteren må settes til CharSet.Ansi. Ellers ville vi gjøre et wchar_tutvalg i stedet for et chararray. Dermed vil den riktige koden være som følger:

[Serializable]
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct LPRData
{
    [MarshalAsAttribute(UnmanagedType.ByValTStr, SizeConst = 15)]
    public string data;

    [MarshalAsAttribute(UnmanagedType.ByValArray, SizeConst = 15)]
    public int[] prob;
}
Svarte 08/02/2012 kl. 07:20
kilden bruker

stemmer
2

Visste du merke GetData parameter med OutAttribute ?

Ved å kombinere den InAttribute og OutAttribute er spesielt nyttig når den anvendes på matriser og formatert og blittable typer. Innringere se endringene en callee gjør disse typene bare når du bruker begge attributter.

Svarte 18/10/2008 kl. 21:42
kilden bruker

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more