Pregunta

Tengo la siguiente estructura en C ++:

#define MAXCHARS 15

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

Y una función en la que estoy invocando para obtener una matriz de 3 de estas estructuras:

void GetData(LPRData *data);

En C ++ simplemente haría algo como esto:

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

Y funcionaría bien, pero en C # parece que no puedo hacer que funcione. He creado una estructura C # como esta:

public struct LPRData
{

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

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

Y si inicializo una matriz de 3 de ellos (y todas sus sub-matrices) y la paso a esto:

GetData(LPRData[] data);

Regresa con éxito, pero los datos en la matriz LPRData no han cambiado.

Incluso intenté crear una matriz de bytes sin procesar del tamaño de 3 LPRData y pasarla a un prototipo de función como este:

GetData (byte [] datos);

Pero en ese caso obtendré los "datos" cadena de la primera estructura LPRData, pero nada después, incluido el "prob" matriz del mismo LPRData.

¿Alguna idea de cómo manejar esto correctamente?

¿Fue útil?

Solución

Intentaría agregar algunos atributos a su estructura 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;
}

* Nota TotalBytesInStruct no está destinado a representar una variable

JaredPar también tiene razón en que usar la clase IntPtr podría ser útil, pero ha pasado bastante tiempo desde que usé PInvoke, así que estoy oxidado.

Otros consejos

Un truco cuando se trata de punteros es usar un IntPtr. Luego puede usar Marshal.PtrToStructure en el puntero e incrementar según el tamaño de la estructura para obtener sus resultados.

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

El Asistente de interoperabilidad PInvoke puede ayudar. http://clrinterop.codeplex.com/releases/view/14120

¿Marcó el parámetro GetData con OutAttribute ?

  

Combinando InAttribute y   OutAttribute es particularmente útil   cuando se aplica a matrices y formateado,   tipos no blittables. Las personas que llaman ven el   cambios que hace un llamado a estos tipos   solo cuando aplica ambos atributos.

Se discutió un tema similar en esta pregunta , y la de La conclusión fue que el parámetro con nombre CharSet debe establecerse en CharSet.Ansi . De lo contrario, estaríamos haciendo una matriz wchar_t en lugar de una matriz char . Por lo tanto, el código correcto sería el siguiente:

[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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top