Domanda

Faccio davvero fatica a mettere a punto questo smistamento.

Ho un codice umanizzato che assomiglia a questo:

WORD HLP_GetDeviceNames (LPSTR *DevNames, WORD Max_Len, WORD Max_Num)

Solo per tua informazione non ho scritto questo codice non gestito ma devo usarlo.

Ritorna:WORD che indica un errore.

Nomi sviluppatore:Puntatore a un array di array di caratteri.Fondamentalmente una serie di stringhe che verranno modificate e restituite a me!

Max_Len:Lunghezza di ciascuna stringa (mi è stato detto che deve essere 256)

Numero_max:Lunghezza dell'array.Sto utilizzando un'altra chiamata Invoke che funziona e mi dice il numero di dispositivi, quindi so esattamente quante stringhe inviare.

Ho utilizzato P/Invoke interop SignatureToolkit per capire molto di questo, ma ne ho anche letto un sacco per andare ancora oltre.Dove sono adesso è qui:

[DllImport("UsbMeasLib.dll")]
public static extern ushort HLP_GetDeviceNames([MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)] ref StringBuilder[] DevNames, ushort Max_Len, ushort Max_Num);

Chiamo il mio codice in questo modo:

StringBuilder[] DevNames = new StringBuilder[deviceCount];
     for(int i = 0; i< deviceCount; i++)
     {
           DevNames[i] = new StringBuilder().Append(' ', 256);
     }

     HachUsbMeasLib.HLP_GetDeviceNames(ref DevNames, 256, Convert.ToUInt16(DevNames.Count())); 

Sto utilizzando l'array del generatore di stringhe perché ho bisogno del codice non gestito per modificare il generatore di stringhe in modo che possa restituire la nuova stringa poiché la stringa non è modificabile.

Quando eseguo il codice, il mio array non è modificato!

Non sono proprio sicuro di cosa stia succedendo, ma penso che abbia qualcosa a che fare con CLR che dice al codice non gestito di non modificare il mio array sul posto ma crea invece un nuovo riferimento (puntatore).Anche se questo è il caso, non so come risolverlo.

Grazie per qualsiasi intuizione che qualcuno può offrire!

È stato utile?

Soluzione 2

Ho capito questo.Grazie a chiunque abbia risposto.

Ho scoperto come funziona.Fornisco semplicemente lo spazio di memoria, ma devo far sapere al marshalling che mi aspetto di entrare e uscire da questo oggetto in modo che consenta al codice non gestito di modificare lo spazio allocato.

L'ho fatto in questo modo:

[DllImport("UsbMeasLib.dll")]
private static extern ushort HLP_GetDeviceNames([In, Out, MarshalAs(UnmanagedType.LPArray, ArraySubType=UnmanagedType.LPStr)] string[] DevNames, ushort Max_Len, ushort Max_Num);

Utilizzo la stringa anziché il generatore di stringhe perché il codice non gestito sostituirà semplicemente la stringa che è ok.Sto recuperando il puntatore dell'array, non le stringhe modificate.il codice gestito sta semplicemente modificando una serie di puntatori in modo che puntino a nuovi oggetti stringa (credo).

int numDev = HLP_GetNumDevices();


string[] names = new string[numDev];

for (int i = 0; i < names.Length; i++)
{
    names[i] = new StringBuilder().Append(' ', 256).ToString();
}

ushort errorCode = HLP_GetDeviceNames(names, 256, Convert.ToUInt16(numDev));

Alloco memoria per il codice non gestito, quindi lascio che il codice non gestito cambi le stringhe lì.

Funziona ma non so se ho potenziali perdite di memoria o altri potenziali problemi.

Altri suggerimenti

Prova a lavorare a un livello basso.Dichiarare il parametro DevNames come IntPtr[].Preparatelo nel modo seguente:

IntPtr[] devNames = new IntPtr[deviceCount];

for(int i = 0; i < deviceCount; i++) 
{ 
    devNames[i] = Marshal.AllocHGlobal[256];
}

Passa questo array a HLP_GetDeviceNames.Per gestire i dati di output, applica Marshal.PtrToStringAnsi a ogni membro DevNames.Alla fine, non dimenticare di rilasciare DevNames[i] con Marshal.FreeHGlobal.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top