Pergunta

Eu tenho o seguinte struct em C ++:

#define MAXCHARS 15

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

E uma função que eu estou p / invocar para obter uma matriz de 3 destas estruturas:

void GetData(LPRData *data);

Em C ++ Gostaria apenas de fazer algo parecido com isto:

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

E isso iria funcionar muito bem, mas em C # Eu não consigo fazê-lo funcionar. Eu criei um C # struct como este:

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 eu inicializar uma matriz de 3 daqueles (e todos os seus sub-matrizes) e passá-lo para o seguinte:

GetData(LPRData[] data);

Ele retorna com sucesso, mas os dados na matriz LPRData não mudou.

Eu mesmo tentou criar uma matriz de bytes matéria do tamanho de 3 LPRData do e passar isso para um protótipo de função como esta:

GetData (byte [] de dados);

Mas, nesse caso vou receber a string "dados" desde a primeira estrutura LPRData, mas nada depois disso, incluindo a matriz "prov" do mesmo LPRData.

Todas as idéias de como lidar corretamente com isso?

Foi útil?

Solução

Gostaria de tentar adicionar alguns atributos para o seu 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;
}

* Nota TotalBytesInStruct não pretende representar uma variável

JaredPar também é correto que o uso da classe IntPtr poderia ser útil, mas tem sido um bom tempo desde que eu usei PInvoke por isso estou enferrujado.

Outras dicas

Um truque quando se lida com ponteiros é usar apenas um IntPtr. Você pode então usar Marshal.PtrToStructure no ponteiro e incremento com base no tamanho da estrutura para obter seus 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;
}

A Interop Assistant PInvoke pode ajudar. http://clrinterop.codeplex.com/releases/view/14120

Você quis marcar GetData parâmetro com OutAttribute ?

Combinando o InAttribute e OutAttribute é particularmente útil quando aplicada a matrizes e formatado, tipos não-blittable. Chamadores ver a muda um callee marcas para esses tipos somente quando você aplicar os dois atributos.

Um tópico semelhante foi discutido na esta questão , eo de as conclusões foi que a CharSet chamado parâmetro deve ser definido como CharSet.Ansi. Caso contrário, estaríamos fazendo uma matriz wchar_t em vez de uma matriz char. Assim, o código correto seria o seguinte:

[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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top