Sto provando a scrivere un wrapper C# P/Invoke per un'API C (una dll nativa per Win), e in genere funziona correttamente. L'unica eccezione è un metodo specifico che prende una struct come parametro nel codice C. La funzione è invocata senza eccezioni, ma restituisce false indicando che qualcosa non è riuscito nell'esecuzione.C# P/Invoke structure problem
Nell'intestazione API depositare il metodo coinvolti e struct sono definiti come segue:
#define MAX_ICE_MS_TRACK_LENGTH 256
typedef struct tagTRACKDATA
{
UINT nLength;
BYTE TrackData[MAX_ICE_MS_TRACK_LENGTH];
} TRACKDATA, FAR* LPTRACKDATA;
typedef const LPTRACKDATA LPCTRACKDATA;
BOOL ICEAPI EncodeMagstripe(HDC /*hDC*/,
LPCTRACKDATA /*pTrack1*/,
LPCTRACKDATA /*pTrack2*/,
LPCTRACKDATA /*pTrack3*/,
LPCTRACKDATA /*reserved*/);
Ho fatto un tentativo di creare un C# P/Invoke involucro utilizzando il codice seguente:
public const int MAX_ICE_MS_TRACK_LENGTH = 256;
[StructLayout(LayoutKind.Sequential)]
public class MSTrackData {
public UInt32 nLength;
public readonly Byte[] TrackData = new byte[MAX_ICE_MS_TRACK_LENGTH];
}
[DllImport("ICE_API.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern bool EncodeMagstripe(IntPtr hDC,
[In]ref MSTrackData pTrack1,
[In]ref MSTrackData pTrack2,
[In]ref MSTrackData pTrack3,
[In]ref MSTrackData reserved);
Poi cerco di richiamare il metodo EncodeMagstripe utilizzando il seguente codice C#:
CardApi.MSTrackData trackNull = null;
CardApi.MSTrackData track2 = new CardApi.TrackData();
byte[] trackBytes = Encoding.ASCII.GetBytes(";?");
track2.nLength = (uint)trackBytes.Length;
Buffer.BlockCopy(trackBytes, 0, track2.TrackData, 0, trackBytes.Length);
if (!CardApi.EncodeMagstripe(hDC, ref trackNull, ref track2, ref trackNull, ref trackNull)) {
throw new ApplicationException("EncodeMagstripe failed", Marshal.GetLastWin32Error());
}
Th fa sì che venga lanciata una ApplicationException e il codice di errore è 801 che, secondo la documentazione, significa che "Dati include troppi caratteri per il formato di traccia 2 selezionato". Tuttavia il formato di traccia selezionato dovrebbe consentire fino a 39 caratteri (ho anche provato stringhe più corte).
Sospetto che il problema si verifichi a causa di qualcosa che ho sbagliato nella definizione di MSTrackData, ma non riesco a vedere cosa possa essere. Qualcuno ha qualche suggerimento?
L'ICEAPI fa riferimento a WINAPI, quindi ho anche impostato "CallingConvention = CallingConvention.Winapi" nell'attributo DllImport. Dopo aver implementato il vostro suggerimento, la chiamata ha funzionato perfettamente :-) Grazie mille :-) –