Como P / Invoke quando os ponteiros estão envolvidos
Pergunta
Em uma tentativa de aprender a usar PInvoke em C #, eu sou um pouco inseguro sobre como lidar com vários casos com ponteiros envolvendo tipos de valores simples.
Eu estou importando as duas seguintes funções a partir de uma DLL não gerenciada:
public int USB4_Initialize(short* device);
public int USB4_GetCount(short device, short encoder, unsigned long* value);
A primeira função utiliza o ponteiro como uma entrada, o segundo como uma saída. Seu uso é bastante simples em C ++:
// Pointer as an input
short device = 0; // Always using device 0.
USB4_Initialize(&device);
// Pointer as an output
unsigned long count;
USB4_GetCount(0,0,&count); // count is output
A minha primeira tentativa em C resulta # na seguinte P / Invoca:
[DllImport("USB4.dll")]
public static extern int USB4_Initialize(IntPtr deviceCount); //short*
[DllImport("USB4.dll")]
public static extern int USB4_GetCount(short deviceNumber, short encoder, IntPtr value); //ulong*
Como posso usar essas funções em C #, da mesma forma como o C ++ código acima? Existe uma maneira melhor para declarar esses tipos, talvez usando MarshalAs
?
Solução
Se o ponteiro está a um único tipo primitivo e não uma matriz, use ref / out para descrever o parâmetro
[DllImport("USB4.dll")]
public static extern int USB4_Initialize(ref short deviceCount);
[DllImport("USB4.dll")]
public static extern int USB4_GetCount(short deviceNumber, short encoder, ref uint32 value)
Nestes exemplos fora é provavelmente mais apropriado mas nem vai funcionar.
Outras dicas
O tempo de execução .NET pode fazer um monte de que a conversão (referido como "empacotamento") para você. Enquanto um IntPtr explícita sempre vai fazer exatamente o que você diga a ele, você pode provavelmente substituir a palavra-chave ref
para um ponteiro assim.
[DllImport("USB4.dll")]
public static extern int USB4_Initialize(ref short deviceCount); //short*
[DllImport("USB4.dll")]
public static extern int USB4_GetCount(short deviceNumber, short encoder, ref short value); //ulong*
Você pode, em seguida, chamá-los assim:
short count = 0;
USB4_Initialize(ref count);
// use the count variable now.