Domanda

Ho la seguente struttura in C ++:

#define MAXCHARS 15

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

E una funzione in cui sto p / invocando per ottenere una matrice di 3 di queste strutture:

void GetData(LPRData *data);

In C ++ farei semplicemente una cosa del genere:

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

E funzionerebbe bene, ma in C # non riesco a farlo funzionare. Ho creato una struttura C # in questo modo:

public struct LPRData
{

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

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

E se inizializzo un array di 3 di questi (e tutti i loro sotto-array) e lo passo in questo:

GetData(LPRData[] data);

Ritorna con successo, ma i dati nell'array LPRData non sono cambiati.

Ho anche provato a creare un array di byte non elaborati della dimensione di 3 LPRData e passarlo in un prototipo di funzione come questo:

GetData (byte [] data);

Ma in quel caso otterrò i "dati" stringa dalla prima struttura LPRData, ma nulla dopo, inclusa la "prob" array dallo stesso LPRData.

Qualche idea su come gestirlo correttamente?

È stato utile?

Soluzione

Vorrei provare ad aggiungere alcuni attributi al tuo decloration struct

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

* Nota TotalBytesInStruct non è destinato a rappresentare una variabile

JaredPar ha anche ragione nel dire che usare la classe IntPtr potrebbe essere utile, ma è da un po 'che non uso PInvoke, quindi sono arrugginito.

Altri suggerimenti

Un trucco quando si hanno a che fare con i puntatori è usare solo IntPtr. È quindi possibile utilizzare Marshal.PtrToStructure sul puntatore e incrementare in base alla dimensione della struttura per ottenere i risultati.

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

PInvoke Interop Assistant può essere d'aiuto. http://clrinterop.codeplex.com/releases/view/14120

Hai contrassegnato il parametro GetData con OutAttribute ?

  

Combinazione di InAttribute e   OutAttribute è particolarmente utile   quando applicato ad array e formattato,   tipi non Blittable. I chiamanti vedono il   le modifiche apportate da una chiamata a questi tipi   solo quando applichi entrambi gli attributi.

Un argomento simile è stato discusso su questa domanda e quella di le conclusioni sono state che il parametro CharSet deve essere impostato su CharSet.Ansi . Altrimenti, creeremmo un array wchar_t anziché un array char . Pertanto, il codice corretto sarebbe il seguente:

[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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top