C++ 原型函数:
IC卡读写操作
原型: int IccIsoCommand(int   slot, 
APDU_SEND  *ApduSend,
APDU_RESP  *ApduRecv,
unsigned char *Response,
 DWORD size
)
功能描述: 读写IC卡
输入参数: slot   卡头索引号
ApduSend   发送的数据,结构如下:
typedef struct 
{
unsigned char Command[4]; // 命令头
unsigned int Lc; // 要发送的数据长度
unsigned char *DataIn; // 要发送的数据缓冲
unsigned int Le; // 要接收的数据长度
} APDU_SEND;
输出参数: ApduRecv   接收的数据,结构如下:
typedef struct
{
unsigned int LenOut;
unsigned char *DataOut;
unsigned char SWA;
unsigned char SWB;
} APDU_RESP;
输出参数: unsigned char *Response, 实际数据加两个状态字;
输出参数: DWORD size , 数据长度加2(两个状态字). 返回值: 0 - 成功
1 - ERROR CARD
7 - ICCISOCOMMAND ERROR
8 - AUTO RESPONSE ERROR
C# 调用代码声明:
[DllImport("SmartCard.dll", EntryPoint = "IccIsoCommand", SetLastError = true)]
        public static extern int IccIsoCommand(int slot,  ref APDU_SEND ApduSend, ref APDU_RESPU ApduRecv ,byte []response,uint size);
定义与C++对应的结构体及一个byte类型数组:byte []BYTE1 = new byte[20];
        [StructLayout(LayoutKind.Sequential)]
        public struct APDU_SEND
        {
            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
            public byte[] Command;
            [MarshalAs(UnmanagedType.U4 , SizeConst = 4)]
            public uint Lc;
            //[MarshalAs(UnmanagedType.LPArray)]
            public unsafe  byte *p;
             
            //public string DataIn;
            //public byte[] DataIn;//byte 数组指针
            //public StringBuilder DataIn;
            [MarshalAs(UnmanagedType.U4 , SizeConst = 4)]
            public uint Le;
        }        [StructLayout(LayoutKind.Sequential)]
        public struct APDU_RESPU
        {
            [MarshalAs(UnmanagedType.U4 , SizeConst = 4)]
            public uint LenOut;
            //[MarshalAs(UnmanagedType.LPArray)]
            //public string DataOut;
            //public StringBuilder DataOut;
            //public byte[] DataOut;
            public unsafe   byte *p ;
            
            [MarshalAs(UnmanagedType.U1, SizeConst = 1)]
            public byte SWA;
            [MarshalAs(UnmanagedType.U1, SizeConst = 1)]
            public byte SWB;
        }调用代码:
            APDU_SEND SS = new APDU_SEND();
            APDU_RESPU RR = new APDU_RESPU();            SS.Command = new byte[4] { 0x00, 0xa4, 0x00, 0x00 };
           
            //SS.DataIn = "3f00";
            //IntPtr p = Marshal.AllocHGlobal(5);
            //Marshal.Copy(BYTE1 ,0,SS.p ,5);
            BYTE1[0] = 0X3f;
            BYTE1[1] = 0X00;
            unsafe 
            {                fixed (byte* p = &BYTE1[0]) 
               {
                   //SS.p = 0Xff;
                   SS.p = p;
               }
            };
            SS.Le = 128;
            SS.Lc = 02;
            byte[] Response = new byte[10];
            
            try
            {
                int result = IccIsoCommand(2, ref  SS, ref RR, Response,130);
                MessageBox.Show("result = " + result);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }为什么会出现not supported Exception这种异常抛出呢?所有DLL函数出现错误都是出现这种错误吗?我的程序错在哪里呢?有位技术比较好的朋友说C++ 接口定义不对,要改写,不知道是不是真的。请各位高手看看,最好能给你一个完整点代码啊
   

解决方案 »

  1.   

    删掉c++代码,解雇c++程序员。如果确实不需要c#来写,那么外包(哪怕给给人)并且要求按期完成就好了,由对方负责进行压力测试。
      

  2.   

    C++程序如果是你们自行开发的,那么与上层C#交互,中间加一层C++/CLI的Wrap,不要用PInvoke,
    不规范的结构体定义或导出函数参数定义,会造成很多莫名其妙的PInvoke问题.另外直接在结构体里定义char*,实在不敢恭维
      

  3.   

    你的C++函数是stdcall吗?另外结构中
    //public byte[] DataIn;定义成数组更好一些。
    关键是分配,我看你定义成指针,但是下面的分配不对吧。做个桥:
    如果实在不好解决,那就用VC再次对该函数进行封装,将他的参数精简或修改为C#方便调用的类型。
      

  4.   

    public byte[] DataIn,我在C#里面定义可以吗?
    C++里面定义的是 char * 类型,这样可以对应上吗?
    期待你回答。
      

  5.   

    先用dumpbin -exports 检查dll里面IccIsoCommand方法是不是确实是IccIsoCommand名字;
      

  6.   

    将c#中对应的struct中的字段修改如下:
    我只改了struct APDU_SEND,你可以把其他也改了试试
    [StructLayout(LayoutKind.Sequential)]
      public struct APDU_SEND
      {
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]//格式要求可以不用,除非c++中是宽字节
    public string Command;
      
    public int Lc;
      
    public StringBuilder DataIn;//char*用StringBuilder对应
        
      //public string DataIn;
      //public byte[] DataIn;//byte 数组指针
      //public StringBuilder DataIn;
    public int Le;
      }c++   ----   c#  格式对应
    char ---- string
    int ----  int
    char* ----StringBuilder
    这几个对应我试过,如果c++中字符行有中文,要改成w_char,用StringBuilder对应
      

  7.   

    IccIsoCommand里面会不会setlasterror?
    不会的话把声明里的setlasterror=true去掉
      

  8.   

    看函数的返回值应该是没设置的了.
    把SetLastError=true去掉后检查一下程序功能是否有异常.
    没有的话应该没啥问题了
      

  9.   

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.IO.Ports;
    using System.Security.Cryptography;
    using System.IO;
    using System.Runtime.InteropServices;
    using System.Threading;namespace MIF
    {    public class IMIF  
        {
            Mutex mut = new Mutex();
            void WaitOne(string Name )
            {
               // Console.WriteLine("{0} WaitOne+++++++++++++++++++++++++++++++++", Name );
                mut.WaitOne();
                
            }
            void ReleaseMutex(string Name)
            {
                mut.ReleaseMutex();
               // Console.WriteLine("{0} ReleaseMutex++++++++++++++++++++++++++++", Name);
            }        #region IC卡相关枚举和常量
            public enum PICC
            {
                PICC_REQIDL = 0x26,
                PICC_REQALL = 0x52
            }
            public enum MIF
            {
                MIF_succeed, MIF_EexistCard, MIF_NoCard, MIF_EexistCardNONum
            }
            public enum MI
            {
                MI_OK = 0,
                MI_CHK_OK = 0,
                MI_CRC_ZERO = 0,
                MI_CRC_NOTZERO = 1,
                MI_NOTAGERR = -1,
                OpenErr = -1,
                MI_CHK_FAILED = -1,
                MI_CRCERR = -2,
                MI_CHK_COMPERR = -2,
                MI_EMPTY = -3,
                MI_AUTHERR = -4,
                MI_PARITYERR = -5,
                MI_CODEERR = -6,
                MI_SERNRERR = -8,
                MI_KEYERR = -9,
                MI_NOTAUTHERR = -10,
                MI_BITCOUNTERR = -11,
                MI_BYTECOUNTERR = -12,
                MI_IDLE = -13,
                MI_TRANSERR = -14,
                MI_WRITEERR = -15,
                MI_INCRERR = -16,
                MI_DECRERR = -17,
                MI_READERR = -18,
                MI_OVFLERR = -19,
                MI_POLLING = -20,
                MI_FRAMINGERR = -21,
                MI_ACCESSERR = -22,
                MI_UNKNOWN_COMMAND = -23,
                MI_COLLERR = -24,
                MI_RESETERR = -25,       /// 复位错误 IC 没有正确响应*/
                MI_INITERR = -25,
                MI_INTERFACEERR = -26,
                MI_ACCESSTIMEOUT = -27,
                MI_NOBITWISEANTICOLL = -28,
                MI_QUIT = -30,
                MI_RECBUF_OVERFLOW = -50,
                MI_SENDBYTENR = -51,
                MI_SENDBUF_OVERFLOW = -53,
                MI_BAUDRATE_NOT_SUPPORTED = -54,
                MI_SAME_BAUDRATE_REQUIRED = -55,
                MI_WRONG_PARAMETER_VALUE = -60
            }
            public enum USR
            {
                USR_Start1 = 0x55,//开始位第一位
                USR_Start2 = 0xAA,//开始位第二位
                USR_Request = 0x01,        /// 寻卡 防碰撞获得卡号*/
                USR_Select = 0x02,       /// 选择卡*/
                USR_PiccRead = 0x03,        /// 读卡*/
                USR_PiccWrite = 0x04,        /// 写卡*/
                USR_PiccHalt = 0x05,        /// 挂起*/
                USR_PcdRfReset = 0x06,        /// 复位M1 卡 + 时间(ms) =2*/
                USR_LoadKeyE2 = 0x10,        /// 下载密钥 到E2 存储器 可掉电存储*/
                USR_PiccAuthE2 = 0x11,        /// 从E2 验证密钥*/
                USR_BuzzSwitch = 0x30,        /// 蜂鸣器开关1=on 0=off*/
                USR_LoadKeyTMP = 0x50,        /// 下载临时key    类似USR_LoadKeyE2 */
                USR_Switch_KEY = 0x62,       /// 切换KEY 类似USR_BuzzSwitch*/
                KeyCommandLen = 0x9
            }
            public enum Secteur
            {
                Secteur0 = 0x00, //第一扇区
                Secteur1 = 0x01, //第一扇区
                Secteur2 = 0x02, //第一扇区
                Secteur3 = 0x03, //第一扇区
                PICC_AUTHENT1A = 0x60,
                PICC_AUTHENT1B = 0x61,
                KEYA = 0x60,
            }
            //抛出消息的定义
            public enum DriverMsg
            {
                /// <summary>
                ///有卡
                /// </summary>
                ExistCard = 1201,
                /// <summary>
                /// 无卡
                /// </summary>
                NotExistCard = 1202,
                /// <summary>
                /// 读写器正常
                /// </summary>
                ReaderNormal = 1941,
                /// <summary>
                /// 读写器异常
                /// </summary>
                ReaderError = 1942,
            }
            //ETC宏定义        public const int CmdLengthSelectSAM = 0x02;
            public const int CmdTypeSelectSAM = 0x80;
            public const int CmdLengthSAMReset = 0x01;
            public const int CmdSAMReset = 0x82;
            public const int CmdLengthGetCardType = 0x02;
            public const int CmdGet_CardType = 0x01;
            //ETC错误码定义
            public enum ETCError
            {
                NO_ERROR = 1,//NO ERROR
                PARAM1_ERROR = -1,//THE 1ST PARAMETER IS WRONG
                PARAM2_ERROR = -2,//THE 2ST PARAMETER IS WRONG
                PARAM3_ERROR = -3,//THE 3ST PARAMETER IS WRONG
                PARAM4_ERROR = -4,//THE 4ST PARAMETER IS WRONG
                PARAM5_ERROR = -5,//THE 5ST PARAMETER IS WRONG
                PORT_NOT_EXIST = -6,//PORT NOT EXIST
                PORT_NOT_OPENED = -7,//PORT NOT OPENED
                PORT_ALREADY_OPENED = -8,//PORT ALREADY OPENED
                PORT_ALREADY_CLOSED = -9,//PORT ALREADY CLOSED
                RX_TIMEOUT_ERROR = -10,//TIMEOUT WHILE RECEIVING DATA
                TX_TIMEOUT_ERROR = -11,//TIMEOUT WHILE TRANSMITTING DATA            FRAME_ERROR = -20,//UNKONWN FRAME TYPE
                CRC_ERROR = -21,//CRC ERROR
                COMMUNICATION_ERROR = -22,//COMMUNICATION ERROR
                READER_NOT_FOUND = -23,//CANNOT FIND READER
                AUTHENTICATION_ERROR = -24,//AUTHENTICATION ERROR
                SEQUENCE_ERROR = -25,//TXSEQ CANNOT MATCH WITH RXSEQ            PICC_NOTAGGERR = -101,//ERROR ON PICC:NO IC CARD IN THE RANGE OF ANTENNA
                PICC_CRCERR = -102,//ERROR ON PICC:CRC16 CHECK ERROR
                PICC_AUTHERR = -103,//ERROR ON PICC:FAILURE ON AUTHENTICATION
                PICC_PARITYERR = -104,//ERROR ON PICC:PARITY CHECK ERROR
                PICC_CODEERR = -105,//ERROR ON PICC:COMMAND ERROR
                PICC_SERNRERR = -106,//ERROR ON PICC:INVALID CARD SERIAL NUMBER
                PICC_KEYERR = -107,//ERROR ON PICC:INVALID KEY
                PICC_NOTAUTHERR = -108,//ERROR ON PICC:INVALID OPERATION
                PICC_BITCOUNTERR = -109,//ERROR ON PICC:UNKOWN FRAME FROM PICC
                PICC_BYTECOUNTERR = -110,//ERROR ON PICC:UNKOWN FRAME FROM PICC
                PICC_FRAMEINGERR = -111,//ERROR ON PICC:UNKOWN FRAME FROM PICC
                PICC_UNKNOWN_COMMAND = -112,//ERROR ON PICC:UNVALID ICC COMMAND
                PICC_COLLERR = -113,//ERROR ON PICC:COLLISION HAPPENED
                PICC_ACCESSTIMEOUT = -114,//ERROR ON PICC:TIMEOUT ON OPERATION
                PICC_NOT_IMPLEMENTED = -115,//ERROR ON PICC:COMMAND NOT EXECUTED
                PICC_WRONG_VALUE = -116,//ERROR ON PICC:INVALID PARAMETER
                PICC_VALERR = -117,//ERROR ON PICC:INVALID VALUE ON ELECTRONIC PURSE OPERATION
                PICC_WRITEERR = -118,//ERROR ON PICC:ERROR ON WRITE CARD
                PICC_OVFLERR = -119,//ERROR ON PICC:READ BUFFER OVERFLOW            PSAM_TIMEOUTERR = -161,//ERROR ON PSAM:TIMEOUT ON OPERATION
                PSAM_CODE_ERR = -162,//ERROR ON PSAM:INVALID PARAMETER
                PSAM_CRCERR = -163,//ERROR ON PSAM:CRC CHECK ERROR            PCD_OUTOFBUFFER = -181,//ERROR ON READER:READER BUFFER OVERFLOW
                PCD_PCCOMMERR = -182,//ERROR ON READER:COMMUNICATION ERROR        }        //错误代码定义
            public enum ErrorType
            {            /// <summary>
                /// 没有错误
                /// </summary>
                NoError = 0,
                /// <summary>
                /// 打开读写器错误
                /// </summary>
                Error_OpenReader = 1,
                /// <summary>
                /// 关闭读写器错误
                /// </summary>
                Error_CloseReader = 2,
                /// <summary>
                /// 输入的参数长度错误
                /// </summary>
                Error_ParamLength = 3,
                /// <summary>
                /// 更新0015文件失败
                /// </summary>
                Error_Update0015_Failed = 4,
                /// <summary>
                /// 执行Pro卡命令失败,返回值不是0x2328
                /// </summary>
                Error_ExcuteProCmd = 5,
                /// <summary>
                /// 取随机数失败
                /// </summary>
                Error_GetRand_Failed = 6,
                /// <summary>
                /// 选择1001目录失败
                /// </summary>
                Error_Select1001_Failed = 7,
                /// <summary>
                /// 打开卡片失败
                /// </summary>
                Error_OpenCard = 8,
                /// <summary>
                /// 执行COS命令错
                /// </summary>
                Error_ExcuteCosCmd = 9,
                /// <summary>
                /// 关闭卡片失败
                /// </summary>
                Error_CloseCard = 10,
                /// <summary>
                /// 读0015文件失败
                /// </summary>
                Error_Read0015_Failed = 11,
                /// <summary>
                /// 读余额失败
                /// </summary>
                Error_ReadBalance = 12,
                /// <summary>
                /// 获取终端机编号错
                /// </summary>            Error_GetTerminalNo = 13,
                /// <summary>
                /// 充值失败
                /// </summary>
                Error_IncreaseMoney = 14,
                /// <summary>
                /// Sam卡复位失败
                /// </summary>
                Error_SamReset = 15,
                /// <summary>
                /// 选择DF01失败
                /// </summary>
                Error_SelectSamDF01 = 16,
                /// <summary>
                /// 扣款失败
                /// </summary>
                Error_DecreaseMoney = 17,
                /// <summary>
                /// 计算MAC1错误
                /// </summary>
                Error_Mac1 = 18,
                /// <summary>
                /// 校验MAC2错误
                /// </summary>
                Error_VerifyMac2 = 19
            }
      
      

  10.   

          public const int CommandRequestLength = 0x02;
            public const int CommandReadLength = 0x04;
            public const int CommandSelecLength = 0x05;
            public const int CommandWriteLength = 0x14;
            public const int CommandBuzzSwitchLength = 0x14;
            public const int CRC8 = 0x80;
            #endregion
            bool _IsComReady = false;
            public bool IsComReady
            {
                get { return _IsComReady; }
                set { _IsComReady = value; }
            }
            protected static SerialPort sp = null;
            public bool Open(string comname)
            {
                if (sp == null)
                {
                    sp = new SerialPort(comname, 115200);
                    sp.ReadTimeout = 2000;
                }
                if (!sp.IsOpen)
                {
                    sp.Open();            }
                IsComReady = sp.IsOpen;
                return sp.IsOpen;
            }
            /// <summary>
            /// 关闭和释放串口
            /// </summary>
            public void Close()
            {
                if (sp != null)
                {
                    if (sp.IsOpen)
                    {
                        sp.Close();                }
                    sp.Dispose();            }
            }        public byte[] Hex2Bin(string hexstr)
            {            byte[] bin = new byte[hexstr.Length / 2];
                for (int i = 0; i < hexstr.Length / 2; i++)
                {
                    bin[i] = (byte)int.Parse(hexstr.Substring(i * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
                }
                return bin;
            }
            public byte[] Hex2Bin(string hexstr, ref byte[] bin)
            {
                for (int i = 0; i < hexstr.Length / 2; i++)
                {
                    bin[i] = (byte)int.Parse(hexstr.Substring(i * 2, 2), System.Globalization.NumberStyles.AllowHexSpecifier);
                }
                return bin;
            }
            public string Bin2Hex(byte[] bin)
            {
                return Bin2Hex(bin, bin.Length);
            }
            public string Bin2Hex(byte[] bin, int Len)
            {
                string result = "";
                byte[] hb = bin;
                for (int i = 0; i < Len; i++)
                {
                    result += hb[i].ToString("X2");
                }
                return result.Trim();
            }        byte[] TempCommand = new byte[1000];
            public byte[] SendCommand(string Command, ref int Len)
            {            return SendCommand(Hex2Bin(Command), ref Len);
                // Hex2Bin(Command, ref TempCommand);
                // return SendCommand(TempCommand, Command.Length / 2, ref Len);
            }
            public byte[] SendCommand(byte[] buffer, ref int Len)
            {
                return SendCommand(buffer, buffer.Length, ref Len);
            }
            /// <summary>
            /// 发送指令并返回返回值
            /// </summary>
            /// <param name="comname">端口名称</param>
            /// <param name="buffer"></param>
            /// <returns></returns>
            byte[] rb = new byte[4096];
            byte[] result = new byte[1000];
            int SendTotal = 0;
            int ReadTotal = 0;
            public byte[] SendCommand(byte[] buffer, int bufferLen, ref int Len)
            {            sp.DiscardInBuffer();
                sp.DiscardOutBuffer();
                SendTotal += bufferLen;
                Console.WriteLine("Send :{0}", SendTotal.ToString());
                sp.Write(buffer, 0, bufferLen);
                System.Threading.Thread.Sleep(10);
                Len = 0;
                int l = 0;
                do
                {
                    l = sp.Read(rb, 0, 4096);
                    Array.Copy(rb, 0, result, Len, l);
                    Len += l;
                    System.Threading.Thread.Sleep(10);
                } while (sp.BytesToRead > 0);
                ReadTotal += Len;
                Console.WriteLine("Read :{0}", ReadTotal.ToString());
                return result;
            }
           
            public bool ResetPro()
            {
                int Len = 0;            
                string rex = Bin2Hex(SendCommand("55aa02060A",ref Len),Len);           
                return rex.EndsWith("00");
            }
          
            byte[] CardNubmerTemp = new byte[50];
            public string  GetCardNumber()
            {
               string CardNubmer =  null;
               WaitOne("GetCardNumber");
               if( ResetPro())
               {
                   CardNubmer = RequestPro();               if (null != CardNubmer)
                   {
                       string cn = "";
                       for (int i = 0; i < 3; i++)
                       {
                           cn += CardNubmer.Substring((2 - i) * 2, 2);  
                       }                   int k = int.Parse(cn, System.Globalization.NumberStyles.HexNumber);
                       CardNubmer = k.ToString();          
                   }
               }
               ReleaseMutex("GetCardNumber");
               return CardNubmer;
            }
            /// <summary>
            /// 请求Pro卡。 
            /// </summary>
            /// <returns>如果有卡, 返回后四位,如果没卡, 返回null</returns>
            public string RequestPro()
            {
                string result = null;
                int Len = 0;            string rex = Bin2Hex(SendCommand("55AA020152", ref Len), Len);
                if (rex != "" )
                {
                    result = rex.Substring(rex.Length - 2 * 4, 2 * 4);
                }
                return result;
            }
     
        }
    }
      

  11.   

    ===========================下面是执行智能卡的指令 /// <summary>
            /// 最终进行执行CPU命令
            /// </summary>
            /// <param name="command">字节之间允许带有空格,则会在第一行就被替换掉</param>
            /// <returns></returns>
            public  byte[] ExcCPUCmd(string command,ref int Len)
            {
              
                //sprintf(chTemp, "%02X%02X%02X%02X%02X%02X%02X%02X%02X%s", USR_Start1, USR_Start2, strlen(command) / 2 + 6, 0x90
                //, strlen(command) / 2 + 4, 0x01, 0x06, 0x0a, 0x00, command);
                command = command.Replace(" ", "");
                string hexcmd = string.Format("{0:X2}{1:X2}{2:X2}{3:X2}{4:X2}{5:X2}{6:X2}{7:X2}{8:X2}{9}",
                     (int)USR.USR_Start1, (int)USR.USR_Start2, command.Replace(" ", "").Length / 2 + 6, 0x90
                     , command.Replace(" ", "").Length / 2 + 4, 0x01, 0x06, (cmdstate ? 0x0a : 0x0b), 0x00, command);
                //(cmdstate ? 0x0a:0x0b) 奇数此是0a ,偶数次是 0b 
                //Console.WriteLine("ExcCPUCmd SendCommand:{0}", hexcmd);
                byte[] b = SendCommand(hexcmd, ref Len);
                cmdstate = !cmdstate;
                //Console.WriteLine("ExcCPUCmd SendCommand:{0}", Bin2Hex(b));
                return b;
            }
            
            /// <summary>
            /// 执行CPU指令
            /// </summary>
            /// <param name="command">命令内容</param>
            /// <param name="strResponse">返回值</param>
            /// <param name="strSW12">执行情况,9000表示成功</param>
            /// <returns>通过判断strSW12是否为9000来判断此处的返回值</returns>
         
            
            public  CPUResult CPU_CommandEx(string command)
            {    
    CPUResult result = new CPUResult();
                COMMAND = command;
                Console.WriteLine("CPU_CommandEx :{0}", COMMAND);
                int Len = 0;
                string strTemp = Bin2Hex(ExcCPUCmd(command,ref Len),Len);            
                //Console.WriteLine("CPU_CommandEx Read :{0}", strTemp);            if ("" != strTemp)
                {
                    if (strTemp.StartsWith("55AA01"))
                    {
                        if (strTemp != "55AA010")
                        {
                            //如果这里成立, 则说明这条命令在读卡器至卡中间出现故障,卡片可能没有接受此命令。 
                            //如有必要请参考ISO14444 在本程序中isready如果为false时, 则需要重新请求卡片-选卡-请求ATS
                            //isready = false;
                            result.RADResult = false;
                        }
                        else
                        {
                            result.RADResult = true;
                        }
                    }
                    else //返回大于一个字节, 返回值无论如何,至少是俩字节。 
                    {                   byte[]   RetLen =  Hex2Bin(strTemp.Substring(4, 2));
                        if (RetLen.Length >= 1)
                        {
                            int rlen = RetLen[0];//返回字节长度
                            if (rlen > 1)
                            {
                                result.RADResult = true;
                                result.PROSW12 = strTemp.Substring(strTemp.Length - 8, 4);
                                int tt = strTemp.Length;
                                result.PROResult = result.PROSW12 == "9000";//握奇 的成功返回值为 9000 
                                SW12 = result.PROSW12;
                                Console.WriteLine("CPU_CommandEx PROSW12: " + SW12);
                                result.PROResponse = strTemp.Substring(0, strTemp.Length - 8).Substring(6 + 6);//回馈值  
                            }
                        }
                    }
                }
                return result;//卡片命令是否执行成功
            }
      

  12.   

    我QQ 191970570,欢迎大家加我。I AM WOMAN
      

  13.   

    21楼原来是女的。
    这个年头碰到个女程序mm真不容易呀。
     int IccIsoCommand(int slot,  
    APDU_SEND *ApduSend,
    APDU_RESP *ApduRecv,
    unsigned char *Response,
     DWORD size
    )int IccIsoCommand(int slot, byte[] ApduSend, byte[] ApduRecv, byte[]Response, int size);
    不用管什么结构体,就用这个试试,看行不行。
    以前写了一段时间的IC卡读写命令,开始真的很烦。
    写习惯了就好了。
    直接使用byte数组写入就行。只要把数据组织好就OK了。
    每次ApduSend的长度是可以预知的,你计算命令及内容长度结果。
    ApduRecv 和 Response是不固定的。因为不知道会给你传回什么数据。
    可以定义的大一些。如果你能估计到最大值的话就好了。反正现在电脑也不缺那点内存。
    定义个几M都行的。
      

  14.   

    unsigned char *Response, C#调用时,输出用ref unit  试试看?
      

  15.   

    或者StringBuilder  输出,记得声明长度
      

  16.   

    貌似是要使用com组件来调用。之前做过税控打印的第三方c++的dll,也是用c#来调用你们的总奸的确是淫才,老牛逼了,膜拜中。最后小小鄙视下 
      

  17.   


    int IccIsoCommand(int slot, byte[] ApduSend, byte[] ApduRecv, byte[]Response, int size);
    你这个是否是声明呀?调用的时对应的 byte[]调用啊,但是定义的时结构体啊,意思是对byte[]数组里面的数组分别赋值吗?请你加我QQ啊
      

  18.   

    给你点资料C++和C#类型对照
    http://topic.csdn.net/u/20090225/15/a6bc50ad-9721-4749-b189-dc4a4bc045a1.html
    http://zhidao.baidu.com/question/90145938.html
    LPSTR     char*     System.String 或 System.Text.StringBuilder    用 ANSI 修饰。
    LPCSTR     Const char*     System.String 或 System.Text.StringBuilder    用 ANSI 修饰。
    LPWSTR     wchar_t*     System.String 或 System.Text.StringBuilder    用 Unicode 修饰。
    LPCWSTR     Const wchar_t*     System.String 或 System.Text.StringBuilder    用 Unicode 修饰。
    FLOAT     Float     System.Single     32 位
    DOUBLE     Double     System.Double     64 位
    CHAR* 可以先实例化一个StringBuilder然后可以传给char*类型 
    关于其他的请参考msdn中的c++与c#的类型转换 
    对应关系如下: 
    C++ ---- C# 
    传入的char*  ----string 
    传出的char* ---- StringBuilder(预分配空间) 
    short  ----short 
    char ---- byte 
    char[n] ---- fixed byte[n] 
    结构指针  ----结构指针 
    函数指针 ---- 委托 C++ C#
    =====================================
    WORD ushort
    DWORD uint
    UCHAR int/byte 大部分情况都可以使用int代替,而如果需要严格对齐的话则应该用bytebyte  
    UCHAR* string/IntPtr
    unsigned char* [MarshalAs(UnmanagedType.LPArray)]byte[]/?(Intptr)
    char* string
    LPCTSTR string
    LPTSTR [MarshalAs(UnmanagedType.LPTStr)] string
    long int
    ulong uint
    Handle IntPtr
    HWND IntPtr
    void* IntPtr
    int int
    int* ref int
    *int IntPtr
    unsigned int uint
    COLORREF uint   
    API与C#的数据类型对应关系表  
    API数据类型 类型描述 C#类型 API数据类型 类型描述 C#类型  
    WORD 16位无符号整数 ushort CHAR 字符 char  
    LONG 32位无符号整数 int DWORDLONG 64位长整数 long  
    DWORD 32位无符号整数 uint HDC 设备描述表句柄 int  
    HANDLE 句柄,32位整数 int HGDIOBJ GDI对象句柄 int  
    UINT 32位无符号整数 uint HINSTANCE 实例句柄 int  
    BOOL 32位布尔型整数 bool HWM 窗口句柄 int  
    LPSTR 指向字符的32位指针 string HPARAM 32位消息参数 int  
    LPCSTR 指向常字符的32位指针 String LPARAM 32位消息参数 int  
    BYTE 字节 byte WPARAM 32位消息参数 int  
      

  19.   

    lz你把SetLastError=true去掉试过了吗?
      

  20.   

    C++ 中unsigned int Le 
    int值比较小,还可以用byte表示,但是int取值超出byte类型了范围以后怎么骂?用byte数组能够表示int取值吗?
    你的意思是不定义结构体吗?直接用byte 数组表示里面的数据吗?我是用我朋友的账号发的
      

  21.   

    把byte数组中元素按C++ 函数中的赋值给参数吗?
    比如 byte[0]到byte[3]赋值给slot,byte[4]到byte[多少]赋值给C++ 结构体ApduSend 对应的变量吗?这个要考虑结构体的对齐问题吗?还有,我发送给程序的指令是16进制的字节流,但是在C++中,成员变量不一样,如何解决数据类型转换的问题呢?
      

  22.   

    参考:http://blog.csdn.net/wo65432519/article/details/6542205