前因后果
調用一門鎖的dll實現讀取酒店IC卡數據,直接用Readme里的方法出錯。
函數聲明:
一、讀卡函數
************************ Delphi 調用 *************************
* function DLL_Read:PChar;
external 'AnLock_2012.dll'; stdcall;
**************************************************************
*
************************* VB 調用 ****************************
* Private Declare Function DLL_Read Lib "AnLock_2012.dll" As String
*
**************************************************************
*
************************* PB 調用 ****************************
* Function String DLL_Read Library "AnLock_2012.dll";
**************************************************************
*
************************* C# 調用 ****************************
* [DllImport("AnLock_2012.dll", EntryPoint = "DLL_Read", CharSet = CharSet.None, SetLastError = false)]
* public static extern String DLL_Read;
**************************************************************
**************************************************************
返回字符串格式說明:
|CardNo 卡號
|CardType 卡片類型
|Building 樓棟號
|Floor 樓層號
|RC 鎖內號(門鎖內定義的房間編號,與房間號一一對應)
|RN 房間號(若無關聯房間號,則為鎖內號)
|StartDT 入住時間
|EndDT 欲離時間
|OpenUnLock 可開反鎖
|AlwaysOpen 常開門
|EndOldCard 終止前卡
**************************************************************
讀卡返回值例子
例1: |CardNo3354970509|CardTypeGuestCard|RC1101|RN1101|StartDT20131209_00:00|EndDT20131214_00:00
以上讀卡信息表示:
卡號為3354970509,卡片類型為GuestCard(賓客卡)
|RC1101|RN1101當不在門鎖系統內鎖內號與房號相等,一般只需處理|RC1101(鎖內號)
|StartDT20131209_00:00|EndDT20131214_00:00 表示入住時間為2013年12月09號0點、退房時間2013年12月14號0點
[DllImport("ANLOCK_2012.dll", EntryPoint = "DLL_Read", CharSet = CharSet.None, SetLastError = false)]
public static extern string DLL_Read();

分析和解決辦法
delphi里導出string估計是使用的pchar,那么C#里面調用時取到是內存地址的句柄才對,試試用IntPtr來接收。一測試OK了。其實問題就是一句話:C# IntPtr與string的互轉。
另外64位操作系統也會報錯,解決辦法就是編譯生成的時候不要用AnyCPU,用x86。
正確的姿勢:
[DllImport("ANLOCK_2012.dll", EntryPoint = "DLL_Read", CharSet = CharSet.None, SetLastError = false)]
public static extern IntPtr DLL_Read();
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var temp = DLL_Read();
string ss = Marshal.PtrToStringAnsi(temp);
textBox1.Text = ss;
//最后釋放掉
//Marshal.FreeHGlobal(temp);
}
