我想用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分了。 

解决方案 »

  1.   

    应该是数据类型的问题dephi                        c++                      C#PChar     32位字符型指针       unsigned char *         StringTHandle   句柄                 *int                       IntPtr
      

  2.   


    PChar 32位字符型指针 [MarshalAs(UnmanagedType.LPArray)]byte[]/?(Intptr
      

  3.   


    这里看不太懂……
    另外,你上面说的,String是c#中的字符型指针吗?我用过String、string和StringBuilder,好像没什么区别,都提示相同的错误。
      

  4.   

    用 [MarshalAs(UnmanagedType.LPArray)]byte[] 试试 32位应该是8个字节  或 Intptr
      

  5.   

    参考[DllImport("SmGwAPI.Dll")]    public extern static int SMGPSendSingle(           int nNeedReply,           string sServiceID,           [MarshalAs(UnmanagedType.LPArray)] byte[]  sMsgID,            ref int nErrorCode   );
      

  6.   


    小声地问一句……
    怎么声明[MarshalAs(UnmanagedType.LPArray)] byte[] 类型的变量?
    我这样写:[MarshalAs(UnmanagedType.LPArray)] byte[] CarNo = new byte[32];
    但是提示语法有错误……
    谢谢你的回答^_^
      

  7.   

    加上引用:
    using System.Runtime.InteropServices;
    [DllImport("SmGwAPI.Dll")] 
        public extern static int SMGPSendSingle( 
              int nNeedReply, 
              string sServiceID, 
             [MarshalAs(UnmanagedType.LPArray)] byte[]  sMsgID, 
              ref int nErrorCode  ); 不会出语法错误.
      

  8.   

    其他地方这样:
    byte[] CarNo = new byte[32]; 
      

  9.   

    [MarshalAs(UnmanagedType.LPArray)] 表示在托管与非托管之间封送数据 只用于DllImport 语句
      

  10.   


    十分感谢你的热情帮忙,
    使用你这个方法可以调用成功了^_^
    不过,发现不用加上“[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的那些参数的返回值。谢谢!
      

  11.   

    ref temp.Money, ref temp.Times, ref temp.Ver 等有ref修饰符的都有返回值。与传进去的不同,在后面直接使用就行了。