我想用c#调用Delphi的dll,但是出现如题错误。详情如下:
有一个Delphi编写的dll文件名为“EastRiver.dll”,
里面有函数:OpenCommPort(打开串行通讯端口,返回端口句柄)、CallClock(显式联机命令)与ReadICCard(读IC卡信息)
函数原型为:
function OpenCommPort(Port: Integer; BaudRate: Integer): Thandle;
function CallClock(hPort: THandle; Clock_id: Integer): Boolean;
function ReadICCard(hPort: THandle; CardNo, CardName: PChar; var Money, Times, Ver: Integer): Boolean;
参数说明:
Port:端口号,允许值1-256,。
BaudRate:端口波特率,允许值:通常是9600。
hPort: 端口句柄, 调用OpenCommPort函数得到。
我编写的一个类代码如下:
namespace 校园一卡通
{
class ReadWriteCard
{
public struct info
{
public StringBuilder CardNo;
public StringBuilder CardName;
public int Money ;
public int Times ;
public int Ver ;
}
public class DllDynamic
{
[DllImport("Kernel32.dll")]
public static extern int LoadLibrary(string lpFileName); [DllImport("Kernel32.dll")]
public static extern bool FreeLibrary(int hModule); [DllImport("Kernel32.dll")]
public static extern IntPtr GetProcAddress(int hModule, string lpProcName);
}
public delegate IntPtr OpenCommPort(int port, int BaudRate);
public delegate bool ReadICCard(IntPtr hPort, ref StringBuilder CardNo, ref StringBuilder CardName, ref int Money, ref int Times, int Ver);
}
}
然后编写另一个类调用它:
namespace 校园一卡通
{
public partial class RWCard : Form
{
static int hDll = ReadWriteCard.DllDynamic.LoadLibrary("EastRiver.dll");
//打开端口
static IntPtr optr = ReadWriteCard.DllDynamic.GetProcAddress(hDll, "OpenCommPort");
ReadWriteCard.OpenCommPort openport = (ReadWriteCard.OpenCommPort)Marshal.GetDelegateForFunctionPointer(optr, typeof(ReadWriteCard.OpenCommPort));
//联机
static IntPtr ccptr = ReadWriteCard.DllDynamic.GetProcAddress(hDll, "CallClock");
ReadWriteCard.CallClock callclock = (ReadWriteCard.CallClock)Marshal.GetDelegateForFunctionPointer(ccptr, typeof(ReadWriteCard.CallClock));
//读卡
static IntPtr rptr = ReadWriteCard.DllDynamic.GetProcAddress(hDll, "ReadICCard");
ReadWriteCard.ReadICCard readcard = (ReadWriteCard.ReadICCard)Marshal.GetDelegateForFunctionPointer(rptr, typeof(ReadWriteCard.ReadICCard)); public RWCard()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
IntPtr portptr = openport(1, 9600);
int port = Int32.Parse(portptr.ToString());
bool isclock;
if (port != -1 && port != 0)
{
//联机
isclock=callclock(portptr, 0)
if (isclock)
{
MessageBox.Show("联机成功!");
//读卡
ReadWriteCard.info temp = new ReadWriteCard.info(); ;
MessageBox.Show("正在读卡...!");
try
{
readcard(portptr,ref temp.CardNo, ref temp.CardName, ref temp.Money, ref temp.Times, 0830);
MessageBox.Show(temp.CardNo.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message+"!","警告:出错了...");
}
}
else
{
MessageBox.Show("联机失败!");
}
}
else if (port == 0)
{
MessageBox.Show("无法打开端口!");
}
else if (port == -1)
{
MessageBox.Show("端口无效或正在使用!");
}
} }
}
但是运行后,出现“尝试读取或写入受保护的内容。这通常指示其他已损坏”错误。
请高手们指教一下,这个问题是如何出现的,应该怎么解决,谢谢!
或者,在c#中怎么调用Delphi的dll?
比如:调用ReadICCard()函数怎么获得其参数的返回值:
【CardNo: 返回卡号,16位, CardName: 返回姓名,长度不小于16位 Money: 返回卡上金额 Times: 返回充值次数】
也就是参数引用的问题;
比如:Delphi的PChar、THandle,用c#怎么表示?
这个问题十分重要,并且也很紧急,希望大侠慷慨相助,谢谢!
我是新手,分数不多,只能给100分了。
有一个Delphi编写的dll文件名为“EastRiver.dll”,
里面有函数:OpenCommPort(打开串行通讯端口,返回端口句柄)、CallClock(显式联机命令)与ReadICCard(读IC卡信息)
函数原型为:
function OpenCommPort(Port: Integer; BaudRate: Integer): Thandle;
function CallClock(hPort: THandle; Clock_id: Integer): Boolean;
function ReadICCard(hPort: THandle; CardNo, CardName: PChar; var Money, Times, Ver: Integer): Boolean;
参数说明:
Port:端口号,允许值1-256,。
BaudRate:端口波特率,允许值:通常是9600。
hPort: 端口句柄, 调用OpenCommPort函数得到。
我编写的一个类代码如下:
namespace 校园一卡通
{
class ReadWriteCard
{
public struct info
{
public StringBuilder CardNo;
public StringBuilder CardName;
public int Money ;
public int Times ;
public int Ver ;
}
public class DllDynamic
{
[DllImport("Kernel32.dll")]
public static extern int LoadLibrary(string lpFileName); [DllImport("Kernel32.dll")]
public static extern bool FreeLibrary(int hModule); [DllImport("Kernel32.dll")]
public static extern IntPtr GetProcAddress(int hModule, string lpProcName);
}
public delegate IntPtr OpenCommPort(int port, int BaudRate);
public delegate bool ReadICCard(IntPtr hPort, ref StringBuilder CardNo, ref StringBuilder CardName, ref int Money, ref int Times, int Ver);
}
}
然后编写另一个类调用它:
namespace 校园一卡通
{
public partial class RWCard : Form
{
static int hDll = ReadWriteCard.DllDynamic.LoadLibrary("EastRiver.dll");
//打开端口
static IntPtr optr = ReadWriteCard.DllDynamic.GetProcAddress(hDll, "OpenCommPort");
ReadWriteCard.OpenCommPort openport = (ReadWriteCard.OpenCommPort)Marshal.GetDelegateForFunctionPointer(optr, typeof(ReadWriteCard.OpenCommPort));
//联机
static IntPtr ccptr = ReadWriteCard.DllDynamic.GetProcAddress(hDll, "CallClock");
ReadWriteCard.CallClock callclock = (ReadWriteCard.CallClock)Marshal.GetDelegateForFunctionPointer(ccptr, typeof(ReadWriteCard.CallClock));
//读卡
static IntPtr rptr = ReadWriteCard.DllDynamic.GetProcAddress(hDll, "ReadICCard");
ReadWriteCard.ReadICCard readcard = (ReadWriteCard.ReadICCard)Marshal.GetDelegateForFunctionPointer(rptr, typeof(ReadWriteCard.ReadICCard)); public RWCard()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
IntPtr portptr = openport(1, 9600);
int port = Int32.Parse(portptr.ToString());
bool isclock;
if (port != -1 && port != 0)
{
//联机
isclock=callclock(portptr, 0)
if (isclock)
{
MessageBox.Show("联机成功!");
//读卡
ReadWriteCard.info temp = new ReadWriteCard.info(); ;
MessageBox.Show("正在读卡...!");
try
{
readcard(portptr,ref temp.CardNo, ref temp.CardName, ref temp.Money, ref temp.Times, 0830);
MessageBox.Show(temp.CardNo.ToString());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message+"!","警告:出错了...");
}
}
else
{
MessageBox.Show("联机失败!");
}
}
else if (port == 0)
{
MessageBox.Show("无法打开端口!");
}
else if (port == -1)
{
MessageBox.Show("端口无效或正在使用!");
}
} }
}
但是运行后,出现“尝试读取或写入受保护的内容。这通常指示其他已损坏”错误。
请高手们指教一下,这个问题是如何出现的,应该怎么解决,谢谢!
或者,在c#中怎么调用Delphi的dll?
比如:调用ReadICCard()函数怎么获得其参数的返回值:
【CardNo: 返回卡号,16位, CardName: 返回姓名,长度不小于16位 Money: 返回卡上金额 Times: 返回充值次数】
也就是参数引用的问题;
比如:Delphi的PChar、THandle,用c#怎么表示?
这个问题十分重要,并且也很紧急,希望大侠慷慨相助,谢谢!
我是新手,分数不多,只能给100分了。
解决方案 »
- asp.net ajax服务器控件
- c# DropDownList绑定xml文件
- 这种写法有何意义?
- 一个很好的代码生成器,生成可修改的C#的web和membership程序源代码
- 通过Reflector for .net(升级的版本)将反编译的类库文件,用vs.net2005打开时为什么还提示升级呢?本来已经是vs.net2005的类库文件,还
- 急!急!急!net 发布错误 无法创建System.int32类型的对象
- WPF设计器窗体大小跟运行时候不一样
- vb6.0中的Me.hdc ,在c#中要用什么来表达?大侠们帮帮忙
- 在线等待:如何在文本框中获取汉字的ASCII码
- C#绘图,如何实现鼠标点击在坐标系中绘制椭圆
- 从索引 0 处开始,初始化字符串的格式不符合规范。
- 判断是否开机
PChar 32位字符型指针 [MarshalAs(UnmanagedType.LPArray)]byte[]/?(Intptr)
这里看不太懂……
另外,你上面说的,String是c#中的字符型指针吗?我用过String、string和StringBuilder,好像没什么区别,都提示相同的错误。
小声地问一句……
怎么声明[MarshalAs(UnmanagedType.LPArray)] byte[] 类型的变量?
我这样写:[MarshalAs(UnmanagedType.LPArray)] byte[] CarNo = new byte[32];
但是提示语法有错误……
谢谢你的回答^_^
using System.Runtime.InteropServices;
[DllImport("SmGwAPI.Dll")]
public extern static int SMGPSendSingle(
int nNeedReply,
string sServiceID,
[MarshalAs(UnmanagedType.LPArray)] byte[] sMsgID,
ref int nErrorCode ); 不会出语法错误.
byte[] CarNo = new byte[32];
十分感谢你的热情帮忙,
使用你这个方法可以调用成功了^_^
不过,发现不用加上“[MarshalAs(UnmanagedType.LPArray)]”也可以。
网上说的其他的类似用ref string、StringBuilder代替PChar都有问题。不过我还想问一个问题,就是定义这个结构体,
public struct info
{
public byte[] CardNo;
public byte[] CardName;
public int Money ;
public int Times ;
public int Ver ;
}
然后在另一个类中,实例化它:
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;
接着调用函数:
ReadWriteCard.ReadICCard(portptr, temp.CardNo, temp.CardName, ref temp.Money, ref temp.Times, ref temp.Ver);
我想问的是,怎么可以取得这个函数调用后的引用参数的返回值呢?就是含有ref的那些参数的返回值。谢谢!