• 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 ;
         }
            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 = ReadWriteCard.readwriteDll.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 = ReadWriteCard.readwriteDll.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 = ReadWriteCard.readwriteDll.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 (ReadWriteCard.readwriteDll.CloseCommPort(Int32.Parse(comboBox1.Text)))
                        {
                            MessageBox.Show("已经关闭端口!");
                        }
                    }
                    else
                    {
                        MessageBox.Show("联机失败!");
                        ReadWriteCard.readwriteDll.CloseCommPort(Int32.Parse(comboBox1.Text));
                    }

                }
                else if (port == 0)
                {
                    MessageBox.Show("无法打开端口!");
                }
                else if (port == -1)
                {
                    MessageBox.Show("端口无效或正在使用!");
                }
            }

  • 相关阅读:
    Centos7安装go.10.1环境
    centos7安装PHP5
    Linux 无文件攻击memfd_create()具体操作步骤
    centos7 '/mnt/hgfs'下共享文件夹不显示问题
    fiddler连接代理手机无法上网问题解决办法
    centos 镜像软件安装包版本低,手动安装过程
    0 upgraded, 0 newly installed, 0 to remove and 112 not upgraded解决方法
    JavaScript高级程序设计(第3版)第七章读书笔记
    JavaScript高级程序设计(第3版)第六章读书笔记
    JavaScript高级程序设计(第3版)第五章读书笔记
  • 原文地址:https://www.cnblogs.com/googlegis/p/2978867.html
Copyright © 2020-2023  润新知