我用C#调用C/C++的.dll文件,程序调试没有问题,但是点击open port与reset port就会出现以下错误:
open port:对 PInvoke 函数“usb key!usb_key.Form1::HD_OpenPort”的调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。请检查 PInvoke 签名的调用约定和参数与非托管的目标签名是否匹配。
reset port:尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
open port 与reset port 函数原型如下:
unsigned short HD_OpenPort(
    short         ivPortNo,//usb端口编号:21,22,23,24
    unsigned      ivBaund,//通信波特率
    short         ivParity,//校验方式,0
    HANDLE        *devNo//返回设备号
)
unsigned short HD_ResetCard(
   HANDLE         devNo,//由HD_OpenPort返回的设备号
   unsigned char  *srATR,//存放收到的数据
   short          *srATRLen,//存放接受到的数据的长度
   short          ivCardSeat//卡座号,1
)我将代码贴在下面:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Runtime.InteropServices;
namespace usb_key
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        public const int WM_DEVICECHANGE = 0x219;
        public const int DBT_DEVNODES_CHANGED = 0x0007;
       
        System.IntPtr hHandle;
        StringBuilder szATR = new StringBuilder("0", 32);
        StringBuilder sData = new StringBuilder("0",180);
        StringBuilder rData = new StringBuilder("0",320);
        StringBuilder key = new StringBuilder("0",32);
        StringBuilder data = new StringBuilder("0",180);
        StringBuilder data2 = new StringBuilder("0",180);
        StringBuilder data3 = new StringBuilder("0",180);
        StringBuilder msg = new StringBuilder("0",180);
        int flag;
        System.UInt16 nATRLen, ReplyLen;
        [DllImport("HDIFD20B.dll", CharSet = CharSet.Auto)]
        public static extern System.UInt16 HD_OpenPort(System.Int16 portNum, System.UInt64 bland, System.Int16 parity, IntPtr hHandle);
        [DllImport("HDIFD20B.dll", CharSet = CharSet.Auto)]
        public static extern System.UInt16 HD_ResetCard(IntPtr hHandle, ref  StringBuilder srATR, ref System.UInt16  srATRLen, System.Int16 ivCardseat);
        //[DllImport("HDIFD20B.dll")]
        //public static extern System.UInt16 HD_ProbeCard(IntPtr hHandle, System.UInt16 ivCardseat);
      protected override void WndProc(ref Message m)
        {
            try
            {
                if (m.Msg == WM_DEVICECHANGE)
                {
                    switch (m.WParam.ToInt32())
                    {
                        case WM_DEVICECHANGE:
                            break;
                        case DBT_DEVNODES_CHANGED:
                            MessageBox.Show("设备有变化");
                            break;
                       
                        default:
                            break;
                    }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            base.WndProc(ref m);
        }        private void cboxAccessories_SelectedIndexChanged(object sender, EventArgs e)
        {        }
        private void btnchoose_Click(object sender, EventArgs e)
        {
            oFDialogSFile.InitialDirectory = "C:\\";
            oFDialogSFile.Filter = "all file(*.*)|*.*";
            oFDialogSFile.RestoreDirectory = true;
            oFDialogSFile.ShowDialog();
            cboxAccessories.Items.Add(oFDialogSFile.FileName.Trim());
            cboxAccessories.Text = oFDialogSFile.FileName.Trim();
        }        private void btncancle_Click(object sender, EventArgs e)
        {
            if (cboxAccessories.Text == "")
            {
                MessageBox.Show("没有要取消的文件!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("确定要删除文件!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                cboxAccessories.Items.Remove(cboxAccessories.Text.Trim());
            }
        }        private void btnopen_Click(object sender, EventArgs e)
        {   
          
            int flag = HD_OpenPort(21, 0, 0, hHandle);//托管签名与非托管的目标签名不匹配(3)
            if (flag != 0x9000)
            { MessageBox.Show("打开设备失败", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); }
            else
            {
                MessageBox.Show("打开设备成功", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
        private void btncheck_Click(object sender, EventArgs e)
        {        //    flag = HD_ProbeCard(hHandle, 1);
        //    while (flag == 0x9000)
        //    {
        //        MessageBox.Show("key已安装", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
        //    }        }
        
        private void btnreset_Click(object sender, EventArgs e)
        {
           
                int flag = HD_ResetCard(hHandle, ref  szATR, ref  nATRLen, 1);
                while (flag == 0x9000)
                {
                    MessageBox.Show("卡复位", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
                   }       
        private void btncode_Click(object sender, EventArgs e)
        {
          
        }        
                      
     
    }        
}

解决方案 »

  1.   

    [DllImport("HDIFD20B.dll", CharSet = CharSet.Auto)] 
            public static extern System.UInt16 HD_OpenPort(System.Int16 portNum, System.UInt64 bland, System.Int16 parity, ref IntPtr hHandle); 加个ref 实验下.
      

  2.   

    单独的unsigned等价于unsigned int        [DllImport("HDIFD20B.dll", CharSet = CharSet.Auto)] 
            public static extern System.UInt16 HD_OpenPort(System.Int16 portNum, System.UInt64 bland, System.Int16 parity, IntPtr hHandle); 第二个参数是64位的吗?
      

  3.   

    谢谢Tassadar1979,将第二个参数改成32位问题就解决了。能不能麻烦你再帮我看看HD_ResetCard(hHandle, ref  szATR, ref  nATRLen, 1)函数问题,谢谢!
      

  4.   

    十万火急!!!!
    unsigned short HD_ResetCard( 
      HANDLE        devNo,//由HD_OpenPort返回的设备号 
      unsigned char  *srATR,//存放收到的数据 
      short          *srATRLen,//存放接受到的数据的长度 
      short          ivCardSeat//卡座号,1 

    各位高手,麻烦帮我看看这个函数的C#声明与调用怎么写呀!
      

  5.   

     System.IntPtr hHandle声明的是指针吗?
    如果是,C#中怎样得到它指向的值?
      

  6.   


    [DllImport("HDIFD20B.dll", CharSet = CharSet.Auto)] 
            public static extern System.UInt16 HD_ResetCard(IntPtr hHandle, ref IntPtr hHandle2, ref System.UInt16  srATRLen, System.Int16 ivCardseat); 
    ________________unsigned char  *srATR,//存放收到的数据 
      short          *srATRLen,//存放接受到的数据的长度
    ___________
    用Marshal.Copy (Char[], Int32, IntPtr, Int32) 把数据从非托管环境拷贝到托管内存下,就随便你操作了.如果不行 Marshal 类,你去msdn上看看,帮助的方法非常的多.
      

  7.   

    请教Tassadar1979:
    我用了marshal.copy,结果出现下面错误:运行库遇到了错误。此错误的地址为 0x79e78a2a,在线程 0x97c 上。错误代码为 0xc0000005。此错误可能是 CLR 中的 bug,或者是用户代码的不安全部分或不可验证部分中的 bug。此 bug 的常见来源包括用户对 COM-interop 或 PInvoke 的封送处理错误,这些错误可能会损坏堆栈。
    代码如下:
     Byte[] szATR = new Byte[32];
     [DllImport("HDIFD20B.dll", CharSet = CharSet.Auto)]
     public static extern System.UInt16 HD_ResetCard( IntPtr hHandle, ref  Byte[] hHandle1, ref IntPtr nATRLen, System.UInt16 ivCardseat);
    private void btnreset_Click(object sender, EventArgs e)
            {
                    Marshal.Copy(hHandle1, szATR, 0, 32);
                    flag = HD_ResetCard(  hHandle, ref szATR,ref nATRLen, 1);
                   while(flag == 0x9000)
                    {
                        MessageBox.Show("卡复位", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
             }
      

  8.   

    unsigned short HD_OpenPort(
        short        ivPortNo,//usb端口编号:21,22,23,24
        unsigned      ivBaund,//通信波特率
        short        ivParity,//校验方式,0
        HANDLE        *devNo//返回设备号
    )
    devNo是HANDLE指针,也就是 void**unsigned short HD_ResetCard(
      HANDLE        devNo,//由HD_OpenPort返回的设备号
      unsigned char  *srATR,//存放收到的数据
      short          *srATRLen,//存放接受到的数据的长度
      short          ivCardSeat//卡座号,1
    )
    devNo是HANDLE,是void*
      

  9.   

    unsigned short HD_ResetCard( 
      HANDLE        devNo,//由HD_OpenPort返回的设备号 
      unsigned char  *srATR,//存放收到的数据 
      short          *srATRLen,//存放接受到的数据的长度 
      short          ivCardSeat//卡座号,1 
    ) __________________________________[DllImport("HDIFD20B.dll", CharSet = CharSet.Auto)] 
    public static extern System.UInt16 HD_ResetCard( IntPtr hHandle, ref  Byte[] hHandle1, ref IntPtr nATRLen, System.UInt16 ivCardseat); 
    ________________________Marshal.Copy (IntPtr, Int16[], Int32, Int32) 
    参数
    source
    内存指针,从中进行复制。 destination
    要复制到的数组。 startIndex
    数组中 Copy 开始位置的从零开始的索引。 length
    要复制的数组元素的数目。 
    写成
    [DllImport("HDIFD20B.dll", CharSet = CharSet.Auto)] 
            public static extern System.UInt16 HD_ResetCard(IntPtr hHandle, ref IntPtr hHandle2, ref System.UInt16  srATRLen, System.Int16 ivCardseat); 
    ..............
    HD_ResetCard(p1 , p2 , len, strlen);byte[] buffers = new byte[len];
    Marshal.Copy(p2 , buffers , 0 ,  len);你看行不行.
      

  10.   

    HD_ResetCard(p1 ,ref p2 ,ref len, strlen);