c#调⽤Delphi的dll函数遇到的问题及解决⽅法
c# 调⽤Delphi的dll时,
1.如果dll中的函数参数含有var,则c#中要加上ref(引⽤);
否则,会有提⽰错误:“尝试读取或写⼊受保护的内容。这通常指⽰其他内存已损坏”。
2.如果dll中的参数是THandle类型,在c#中⽤IntPtr代替。
3.如果dll中的参数是PChar类型,在c#中应该⽤byte[]代替。
使⽤⽹上说的⽤ref string或StringBuilder代替PChar都有问题。
另外,这⾥有⼀些类型对照:
dephi c++ C#
PChar 32位字符型指针 unsigned char * String /byte[]
THandle 句柄 *int IntPtr
下⾯是具体例⼦:
==============================================================================================假设有⼀个Delphi写的dll名字为“EastRiver.dll”;
它的函数有:
(1)OpenCommPort: 打开串⾏通讯端⼝
语法:
function OpenCommPort(Port: Integer; BaudRate: Integer): Thandle;
参数说明: Port:端⼝号,允许值1-256。 BaudRate:端⼝波特率,允许值:通常是9600。。
如果函数调⽤成功,返回的值就是端⼝句柄,⽤于其它函数调⽤。当返回的值是-1时,端⼝⽆效或正在使⽤;当返回的值是0时,⽆法打开
端⼝。
(2) CallClock: 显式联机命令
语法:
function CallClock(hPort: THandle; Clock_id: Integer): Boolean;
参数说明:
hPort: 端⼝句柄,通过调⽤OpenCommPort函数得到
clock_id: 机号,允许值: 0-255。
返回变量: 如果返回为True表⽰联机成功,如果返回为False表⽰联机失败。
(3)ReadICCard: 读IC卡信息
语法:
function ReadICCard(hPort: THandle; CardNo, CardName: PChar; var Money, Times, Ver: Integer): Boolean;
参数说明:
hPort: 端⼝句柄, 调⽤OpenCommPort函数得到,需要联机
CardNo: 返回卡号,16位,
CardName: 返回姓名,长度不⼩于16位
Money: 返回卡上⾦额 Times: 返回充值次数
Ver: IC卡格式, 允许值如下: 0830
返回变量: 如果返回False表⽰失败,如果返回True表⽰成功
===========================================================================================
那么,在c#中可以使⽤以下⽅法动态加载dll:
class ReadWriteCard
{
public struct info
{
public byte[] CardNo;
public byte[] CardName;
public int Money ;
public int Times ;
public int Ver ;
}error parse new
public class readwriteDll
{
[DllImport("EastRiver.dll", EntryPoint = "OpenCommPort", SetLastError = true, CharSet = CharSet.Unicode,
ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr OpenCommPort(int port,int RaudRate);
[DllImport("EastRiver.dll", EntryPoint = "CallClock", SetLastError = true, CharSet = CharSet.Unicode,
ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool CallClock(IntPtr hport, int Clock_id);
[DllImport("EastRiver.dll", EntryPoint = "ReadICCard", SetLastError = true, CharSet = CharSet.Unicode,
ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool ReadICCard(IntPtr hport, byte[] CardNo, byte[] CardName, ref int Money, ref int Times,ref int ver);
}
然后,在另⼀个⽅法调⽤这⾥的函数:
private void button1_Click(object sender, EventArgs e)
{
IntPtr portptr = adwriteDll.OpenCommPort(Int32.Parse(comboBox1.Text),
Int32.Parse(comboBox2.Text));
int port = Int32.Parse(portptr.ToString());
bool isclock;
MessageBox.Show("端⼝句柄:" + portptr);//+port.ToString());
if (port != -1 && port != 0)
{
//联机
isclock = adwriteDll.CallClock(portptr, Int32.Parse(comboBox3.Text));
if (isclock)
{
MessageBox.Show("联机成功!");
//读卡
ReadWriteCard.info temp = new ReadWriteCard.info();
temp.CardNo = new byte[255];
temp.CardName = new byte[255];
temp.Money = 0;
temp.Times = 0;
temp.Ver = 0000;
MessageBox.Show("正在读卡...!");
try
{
bool suc = adwriteDll.ReadICCard(portptr, temp.CardNo, temp.CardName, ref temp.Money, ref temp.Times, ref temp.Ver);
MessageBox.Show(suc.ToString());
if (suc)
{
MessageBox.Show("读卡成功!");
}
else
{
MessageBox.Show("读卡失败!");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "警告:出错了...");
}
MessageBox.Show("正在关闭端⼝...!");
if (adwriteDll.CloseCommPort(Int32.Parse(comboBox1.Text)))
{
MessageBox.Show("已经关闭端⼝!");
}
}
else
{
MessageBox.Show("联机失败!");
}
}
else if (port == 0)
{
MessageBox.Show("⽆法打开端⼝!");
}
else if (port == -1)
{
MessageBox.Show("端⼝⽆效或正在使⽤!"); }
}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论