我需要使用硬體供應商提供的 Delphi 撰寫的 DLL。在提供的檔案中,它提到了以下內容
int ReadCard(char *room, char *gate,char *stime, char *guestname, char *guestid, char *lift, char *track1, char *track2, long *cardno, int *st, int *Breakfast);
引數的進一步闡述如下:
room [out]:字串指標,接收回傳的房間號,推薦10位元組。
gate [out]:字串指標,接收回傳的授權公共門,可以為NULL。
Guestname [out]:字串指標,接收回傳的客人姓名,可以為NULL。
Guestid [out]:字串指標,接收回傳的guest ID,可以為NULL。
Lift[in]:電梯樓層,字串引數,“00”代表默認樓層,“99”代表所有樓層授權,其他為指定樓層代碼,例如“010205”代表三層授權01,02 ,05。
track1 [out]:接收磁卡的磁道1資料,可以為NULL。
track2 [out]:接收磁卡2磁道資料,可以為NULL。
Cardno [out]:長整型指標,接收回傳的卡號,可以為NULL。
St[out]:整數指標,接收回傳卡狀態:1-正常使用,3-正常擦除,4-丟失,5-損壞,6-自動擦除,可以為NULL。早餐
[in]:早餐編號。
這是我的問題 - 在嘗試了各種 DLLImport 方法后,我不斷收到記憶體訪問沖突錯誤。
錯誤內容類似于“System.AccessViolationException: Attempted to read or write protected memory 這通常表明其他記憶體已損壞。” ntdll.dll 拋出錯誤
以下是我嘗試過的一些嘗試:
[DllImport(DLL_FILE_PATH, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public unsafe static extern int ReadCard(
[MarshalAs(UnmanagedType.LPStr)] StringBuilder room,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder gate,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder stayPeriod,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder guestName,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder guestID,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder lift,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder trackData1,
[MarshalAs(UnmanagedType.LPStr)] StringBuilder trackData2,
out Int32[] cardNumber,
out int[] cardStatus,
out int[] breakfast
);
[DllImport(DLL_FILE_PATH, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public unsafe static extern int ReadCard(
[MarshalAs(UnmanagedType.LPStr)] string room,
[MarshalAs(UnmanagedType.LPStr)] string gate,
[MarshalAs(UnmanagedType.LPStr)] string stayPeriod,
[MarshalAs(UnmanagedType.LPStr)] string guestName,
[MarshalAs(UnmanagedType.LPStr)] string guestID,
[MarshalAs(UnmanagedType.LPStr)] string lift,
[MarshalAs(UnmanagedType.LPStr)] string trackData1,
[MarshalAs(UnmanagedType.LPStr)] string trackData2,
out long cardNumber,
out long cardStatus,
out long breakfast
);
[DllImport(DLL_FILE_PATH, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public unsafe static extern int ReadCard(
out char[] room,
out char[] gate,
out char[] stayPeriod,
out char[] guestName,
out char[] guestID,
out char[] lift,
out char[] trackData1,
out char[] trackData2,
out long[] cardNumber,
out int[] cardStatus,
out int[] breakfast
);
[DllImport(DLL_FILE_PATH, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public unsafe static extern int ReadCard(
[MarshalAs(UnmanagedType.LPStr)] out string room,
[MarshalAs(UnmanagedType.LPStr)] out string gate,
[MarshalAs(UnmanagedType.LPStr)] out string stayPeriod,
[MarshalAs(UnmanagedType.LPStr)] out string guestName,
[MarshalAs(UnmanagedType.LPStr)] out string guestID,
[MarshalAs(UnmanagedType.LPStr)] out string lift,
[MarshalAs(UnmanagedType.LPStr)] out string trackData1,
[MarshalAs(UnmanagedType.LPStr)] out string trackData2,
IntPtr cardNumber,
IntPtr cardStatus,
IntPtr breakfast
);
知道我在哪里錯過了嗎?
uj5u.com熱心網友回復:
您不能用于string需要指向緩沖區的指標的輸出引數char[]。StringBuilder根據 Microsoft 的檔案,您需要改用:Default Marshaling for Strings: Fixed-Length String Buffers。對于輸入引數,string將正常作業。
在 C# 中,在 C/C 和 Delphi 中使用long(ie Int64) for int(32bit integer) 引數是錯誤的。您需要使用int(ie Int32) 代替。另一方面,long在 C/C 中,可能是 32 位或 64 位,具體取決于平臺,因此您必須檢查 DLL 實際使用的是什么。有可能,它可能是 32 位,假設 Windows。
但是,你為什么宣告cardNumber,cardStatus以及breakfast引數陣列?檔案或 C/C 宣告中沒有任何內容表明它們不是單個整數。cardNumber并且cardStatus應該是out int(或者可能 out long是cardNumber),或者IntPtr如果你曾經null為他們傳遞過。breakfast只是輸入,所以它應該是簡單的int。
嘗試更像這樣的事情:
[DllImport(DLL_FILE_PATH, CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]
public static extern int ReadCard(
StringBuilder room,
StringBuilder gate,
StringBuilder stayPeriod,
StringBuilder guestName,
StringBuilder guestID,
string lift,
StringBuilder trackData1,
StringBuilder trackData2,
out int cardNumber,
out int cardStatus,
int breakfast
);
從 C# 呼叫它時,只需確保預先將StringBuilder引數預先分配到所需的長度,以便 DLL 有足夠的記憶體可供寫入。例如:
StringBuilder roomSB = new StringBuilder(10);
ReadCard(roomSB, ...);
string room = roomSB.ToString();
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/379298.html
上一篇:如何使用請求正文呼叫API端點?
