Como se pode passar os dados para MemoryStream não gerido C ++ DLL usando P / invocação
-
20-08-2019 - |
Pergunta
Eu preciso de sua ajuda com o seguinte cenário:
Estou lendo alguns dados de hardware em um MemoryStream (C #) e eu preciso passar esses dados na memória para uma dll implementado em não gerenciado C ++ (usando ponteiro ??). A leitura de dados (em fluxo) é muito grande (megabytes). Eu entendo que eu posso P / Invoke esta dll mas o que eu não tenho certeza é como passar o ponteiro / referência dos dados de fluxo para a API C ++?
Devo admitir que estou confuso como eu sou novo para C # - eu preciso para usar inseguro / fixo desde que os dados é grande ou estes são irrelevantes como MemoryStream objeto é gerido por GC? Alguns exemplo de código / descrição detalhada seria muito útil. Graças
Assinatura da API não gerenciado:
BOOL doSomething (void * rawData, dataLength int)
Solução
Se ele está apenas esperando bytes você pode ler o MemoryStream para uma matriz de bytes e, em seguida, passar um ponteiro para que o método.
Você tem que declarar o método externo:
[DllImport("mylibrary.dll", CharSet = CharSet.Auto)]
public static extern bool doSomething(IntPtr rawData, int dataLength);
Em seguida, ler os bytes do MemoryStream para uma matriz de bytes. Alocar um GCHandle que:
Uma vez alocado, você pode usar um GCHandle para evitar o objeto gerenciado a partir de sendo recolhido pelo lixo coletor quando um cliente não gerenciado detém a única referência. sem tal um identificador, o objecto pode ser recolhido pelo coletor de lixo antes completando o seu trabalho em nome da cliente não gerenciado.
E, finalmente, usar o método AddrOfPinnedObject para obter um IntPtr para passar para o dll C ++.
private void CallTheMethod(MemoryStream memStream)
{
byte[] rawData = new byte[memStream.Length];
memStream.Read(rawData, 0, memStream.Length);
GCHandle rawDataHandle = GCHandle.Alloc(rawData, GCHandleType.Pinned);
IntPtr address = handle.AddrOfPinnedObject ();
doSomething(address, rawData.Length);
rawDataHandle.Free();
}