int OneCommand(int cmd, int dlength,BYTE * pBuff,int nTypeAB, int nOutOfTime)
       cmd 2字节命令字,参照具体协议
        dlength 要发送的pBuff中的数据字节数
        pBuff   要发送的数据, 同时也是接收数据缓冲区
        nTypeAB 预留,这里请附0,        //0 TypeA   1 TypeB
       nOutOfTime  接收数据等待超时时间,没有接收到数据,要等待到超时,如果接收到数据,则立即返回
    Return
         >=0   Success, 实际接收到pBuff中的数据长度
          -1    没有接收到数据
          -2    发送错误
          -3: 数据长度越界,最大允许2048
         -10   接收到数据,但数据不正确,一般情况是接收数据校验错误读二代证:
      cmd=0x3001
     dlength=0 发送数据长度为0
     pBuff 缓冲区指针,缓冲区最少1300字节
      nTypeAB=1       1表示读取二代证
      nOutOfTime=1500 超时时间,建议1500ms
    返回数据:pBuff[0]~pBuff[2]标志状态, pBuff[2]==0x90时,说明找读卡成功 此时Return=1288
    pBuff[3],pBuff[4]应该为 0x01,0x00 表示文字信息长度为0x0100 即256字节
     pBuff[5],pBuff[6]应该为 0x04,0x00     表示图片信息长度为0x0400 即1024字节
    从pBuff[7]开始的256字节为文字信息
    从pBuff[7+256]字节开始的1024字节为加密压缩的照片    256字节的文字处理,(文字编码格式为GB13000.1 即Unicode)
    从头向为按字节截取
         项目:  姓名 性别 民族 出生 住址 号码 签发 有效期起 有效期止
字节数:30 2 4 16 70 36 30 16 16
   1024字节的照片处理,需要存储为后缀为.wlt的文件,然后调用相应函数进行解码,得到同名的bmp照片如何写成一个Delphi的函数.
还有能把这个函数随便写几个内容吗?来描述下以上变量怎么用.

解决方案 »

  1.   

    设备的sdk应该提供的是一些接口,你写成delphi的函数有何意义,你只需要使用开发商提供的接口就行了
      

  2.   

    如果是厂家封装成这样,真有点变态了。
    读取二代证厂家一般返回一个固定格式的文本和一个bmp头像。
    你直接到相应目录去读就是了。
      

  3.   

    那个应该是写的vb下调用接口函数说明吧你要根据这个说明写个delphi调用的例子???
      

  4.   

    接口是专门提供给VB的,你转成Pascal语法也不一定能奏效……
      

  5.   

    你可以这样:
    在VB里将接口再次封装,弄出一个新的动态库,供delphi调用。
      

  6.   

    哦,估计没问清楚.
    int OneCommand(int cmd, int dlength,BYTE * pBuff,int nTypeAB, int nOutOfTime) 
    是一个DLL的函数.这个好象是VB的写法吧?
    弄成Delphi怎么写呢?
    我这样搞的:
    function OneCommand(cmd,dlength:smallInt; pBuff:PChar; nTypeAB,nOutOfTime:smallInt): smallInt;
    应该没错吧?
    函数的说明是cmd 传入固定值:0x3001 ,dlength 是发送数据长度为0,pBuff缓冲区指针,缓冲区最少32字节 nTypeAB为0,nOutOfTime为1000.
    那Delphi 写成:
    OneCommand(0x3001,0, pBuff, 1, 1500);0x3001就编译不过去,呵呵.我基础不好, 这样的数字0x3001 在Delphi如何表示呢?
      

  7.   

    int OneCommand(int cmd, int dlength,BYTE * pBuff,int nTypeAB, int nOutOfTime) 
    这是C/C++中的写法,不是VB的
     转成Delphi这样的试试function OneCommand(cmd: Integer; dLength: Integer; pBuff: PByte; nTypeAB: Integer; nOutOfTime: Integer): Integer; Stdcall;另:
    不要忘了Stdcall;
    C/C++的int对应Delphi 中的Integer,实际上只要是类型的长度相同就OK了.本来PBuff可以写成PChar的,但是如果在D2009上工作,肯定不行,因为Char<>byte,类似的情况在VC中也是,主要取决于Char的类型定义
      

  8.   

    怎么用呢?我这样写的:procedure TfrmSc2Main.btnOneCommandClick(Sender: TObject);
    var OneCommand:function (cmd: Integer; dLength: Integer; pBuff: PChar;
      nTypeAB: Integer; nOutOfTime: Integer): Integer; Stdcall;
      pBuff:PChar;
      iReturn:Integer;
    begin
      OneCommand := GetProcAddress(DllHandle,'OneCommand');
      iReturn := OneCommand($3001,0, pBuff, 1, 1500);
      if iReturn<0 then
      begin
        showmessage('error');
        Exit;
      end;
    end;
    但每次都是返回-1,而使用VC的代码却能正确取得数据.
      

  9.   

    function OneCommand(cmd:Word,dlenth:word,pbuff:Pchar,nTypeAb word,nOutOfTime word) : Word ; stdcall
    procedure TfrmSc2Main.btnOneCommandClick(Sender: TObject);  pBuff:PChar;
      iReturn:Integer;
    begin
      getMem(pBuff,1300);
      OneCommand := GetProcAddress(DllHandle,'OneCommand');
      iReturn := OneCommand($3001,0, pBuff, 1, 1500);
      if iReturn<0 then
      begin
        showmessage('error');
        Exit;
      end;
    end;
      

  10.   

    TO starluck :
    执行的iReturn >0 调用Dll好像成功了.
    但是我Showmessage(pBuff);没有得到相应的值.
    并且过程执行完毕会出错.
    我这样写的:(你那种写法是编译不过去的)procedure TfrmSc2Main.btn1Click(Sender: TObject);
    var pBuff:PChar; iReturn:Integer;
    OneCommand:function (cmd:Word;dlenth:word;pbuff:Pchar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
    begin
     // getMem(pBuff,2048);
     pBuff:=StrAlloc(2048);
      OneCommand := GetProcAddress(DllHandle,'OneCommand');
      iReturn := OneCommand($3001,0, pBuff, 1, 1500);
      if iReturn<0 then
      begin
        showmessage('error');
        Exit;
      end else begin
        ShowMessage(pBuff);
      end;
    end;
      

  11.   


    procedure TfrmSc2Main.btn1Click(Sender: TObject);
    var pBuff:PChar; iReturn:Integer;
    OneCommand:function (cmd:Word;dlenth:word;pbuff:Pchar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
    begin
      getMem(pBuff,2048);
     //pBuff:=StrAlloc(2048);
     try
       OneCommand := GetProcAddress(DllHandle,'OneCommand');
       iReturn := OneCommand($3001,0, pBuff, 1, 1500);
       if iReturn<0 then
       begin
         showmessage('error');
       end else begin
         ShowMessage(pBuff[0]);
       end;
     finally
       FreeMem(pBuff);
     end;
    end;
    这个写法,返回的pBuff也没有值.郁闷...
      

  12.   

    procedure TfrmSc2Main.btn1Click(Sender: TObject);
    var pBuff:PChar; iReturn:Integer;
    OneCommand:function (cmd:Word;dlenth:word;pbuff:Pchar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
    begin
      getMem(pBuff,2048);
     //pBuff:=StrAlloc(2048);
     try
       OneCommand := GetProcAddress(DllHandle,'OneCommand');
       iReturn := OneCommand($3001,0, pBuff, 1, 1500);
       if iReturn<0 then
       begin
         showmessage('error');
       end else begin
         ShowMessage(strPas(pbuff));  //这样试下。
       end;
     finally
       FreeMem(pBuff);
     end;
      

  13.   

    嗯.我按照你的写法改了.但是好像后面的两段代码还是行不通呢.取不到值..
    请你多多指教了.呵呵.下面这个是我改了的.但是就是取不到结果返回来的值.就是pBuff为空.不知道怎么搞的..
    不知是不是Pchar和PBtye的问题呢?我实在是个菜鸟,PByte不会用.呵呵.
    procedure TfrmSc2Main.btn1Click(Sender: TObject);
    var pBuff:PChar; iReturn:Integer;
    OneCommand:function (cmd:Word;dlenth:word;pbuff:Pchar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
    begin
      getMem(pBuff,2048);
     //pBuff:=StrAlloc(2048);
     try
       OneCommand := GetProcAddress(DllHandle,'OneCommand');
       iReturn := OneCommand($3001,0, pBuff, 1, 1500);
       if iReturn<0 then
       begin
         showmessage('error');
       end else begin
         ShowMessage(pBuff[0]);
       end;
     finally
       FreeMem(pBuff);
     end;
    end;
      

  14.   

    ShowMessage(strPas(pbuff));  //这样试下。后返回:---------------------------
    Prjshensiselfcard2
    ---------------------------
    飓C
    ---------------------------
    OK   
    ---------------------------并且执行完毕不知道编译器为什么传出一大把错误...
      

  15.   

    原来C代码是这样写的:void CDemoVCDlg::OnButton5() 
    {
    //读身份证卡
        int nRet,i;
        CString ss,ss1;
        BYTE buf[2048];
        if(pOneCommand==NULL)
        {
            m_strEdit.Insert(0,"没有初始化通讯库\r\n");
            UpdateData(FALSE);
            return;
        }    nRet=pOneCommand(PICC_RDRead,0,buf,TYPE_ID2,1500);      //注意超时时间这里为1.5秒
        if(nRet>0)
        {..............................省略代码
      

  16.   


    procedure TfrmSc2Main.btn1Click(Sender: TObject);
    var
       pBuff:PansiChar; iReturn:Integer;
       OneCommand:function (cmd:Word;dlenth:word;pbuff:PAnsichar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
    begin
      getMem(pBuff,2048);
      fillChar(pbuff,2048,#0);
     try
       OneCommand := GetProcAddress(DllHandle,'OneCommand');
       iReturn := OneCommand($3001,0, pBuff, 1, 1500);
       if iReturn<0 then
       begin
         showmessage('error');
       end else begin
         ShowMessage(strPas(pbuff));  //这样试下。
       end;
     finally
       FreeMem(pBuff);
     end; 如果是DELPHI2009,用上面的试试。 
      

  17.   

    procedure TfrmSc2Main.btn1Click(Sender: TObject);
    var
       pBuff:Array[0..2048-1] of AnsiChar;
       iReturn:Integer;
       OneCommand:function (cmd:Word;dlenth:word;var pbuff:array of AnsiChar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
    begin try
       OneCommand := GetProcAddress(DllHandle,'OneCommand');
       iReturn := OneCommand($3001,0, pBuff, 1, 1500);
       if iReturn<0 then
       begin
         showmessage('error');
       end else begin
         ShowMessage((pbuff));  //这样试下。
       end;
     finally
       FreeMem(pBuff);
     end;
      

  18.   

    谢谢starluck ,但是还是不行.我的是Delphi2007.
    我用Delphi2009的代码测试跟踪返回的是空值.
    用最后面的那个Delphi2007的测试返回也是为空.
    并且执行iReturn := OneCommand($3001,0, pBuff, 1, 1500);很快.一般不会哪么快的.毕竟要返回很多信息还有身份证的头像照片.
    因为用C的调试执行这个代码是需要点时间的.大概一秒左右。你用QQ吗、要不我把C的整个源代码给你看看?另:我在上海,如果方便很想结识你这个朋友,搞定这个可酬谢.
      

  19.   

    nRet=pOneCommand(PICC_RDRead,0,buf,TYPE_ID2,1500);      你看下 PICC_RDRead 是多少??  TYPE_ID2 是多少?
    procedure TfrmSc2Main.btn1Click(Sender: TObject);
    var
       pBuff:Array[0..2048-1] of AnsiChar;
       iReturn:Integer;
       OneCommand:function (cmd:Word;dlenth:word;var pbuff:array of AnsiChar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
    begin try
       OneCommand := GetProcAddress(DllHandle,'OneCommand');
       iReturn := OneCommand($3001,0, pBuff, 1, 1500);
       if iReturn<0 then
       begin
         showmessage('error');
       end else begin
         ShowMessage((pbuff));  //这样试下。
       end;
     finally
       FreeMem(pBuff);
     end;
     这样基本上跟C的就一样了。 Ansichar,Byte 都占用的是一个字节
      

  20.   


    //二代证命令
    #define PICC_RDFind             0x2001
    #define PICC_RDAuth             0x2002
    #define PICC_RDRead             0x3001#define TYPE_BANK       0
    #define TYPE_ID2        1
      

  21.   

    我估计是:
    OneCommand:function (cmd:Word;dlenth:word;var pbuff:array of AnsiChar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
    函数与 Dll 函数
    #include "WINDEF.h"
    extern HINSTANCE hModule;
    typedef int (*pFun_OpenComm)(int ,int);
    typedef int (*pFun_bCommConnect)(void);
    typedef int (*pFun_CloseComm)(void);
    typedef int (*pFun_SendData)(int cmd, int dlength,BYTE * pBuff, int nTypeAB);
    typedef int (*pFun_RecvData)(BYTE* pBuff,int nOutOfTime);
    typedef int (*pFun_OneCommand)(int cmd, int dlength,BYTE * pBuff,int nTypeAB, int nOutOfTime);extern pFun_OpenComm  pOpenComm;
    extern pFun_bCommConnect pbCommConnect;
    extern pFun_CloseComm pCloseComm;
    extern pFun_SendData pSendData;
    extern pFun_RecvData pRecvData;
    extern pFun_OneCommand pOneCommand;extern BOOL LoadComDll();
    extern void FreeComDll();
    会冲突.所以导致iReturn := OneCommand($3001,0, pBuff, 1, 1500);根本没执行.
      

  22.   


    #include "StdAfx.h"
    #include "ComDll.h"HINSTANCE hModule;pFun_OpenComm pOpenComm;
    pFun_bCommConnect pbCommConnect;
    pFun_CloseComm pCloseComm;
    pFun_SendData pSendData;
    pFun_RecvData pRecvData;
    pFun_OneCommand pOneCommand;BOOL LoadComDll();
    void FreeComDll();BOOL LoadComDll()
    {
    hModule=LoadLibrary(_T("DllCom.dll"));
    if(hModule ==NULL )
    {
    //AfxMessageBox(_T("加载动态库失败"));
    return FALSE;
    }
    pOpenComm =(pFun_OpenComm)GetProcAddress(hModule,_T("OpenComm"));
    pbCommConnect =(pFun_bCommConnect)GetProcAddress(hModule,_T("bCommConnect"));
    pCloseComm =(pFun_CloseComm)GetProcAddress(hModule,_T("CloseComm"));
    pSendData =(pFun_SendData)GetProcAddress(hModule,_T("SendData"));
    pRecvData =(pFun_RecvData)GetProcAddress(hModule,_T("RecvData"));
    pOneCommand =(pFun_OneCommand)GetProcAddress(hModule,_T("OneCommand")); if(pOpenComm == NULL || pbCommConnect == NULL || pCloseComm == NULL 
       || pSendData == NULL || pRecvData == NULL
       || pOneCommand == NULL )
    {
    return FALSE;
    }
        else
        {
            return TRUE;
        }
    }void FreeComDll()
    {
    if(hModule !=NULL )
    {
    if(pbCommConnect()>0)
    {
    pCloseComm();
    Sleep(500);
    }
    FreeLibrary(hModule);
    hModule=NULL;        pOpenComm=NULL;
            pbCommConnect   =   NULL;
            pCloseComm      =   NULL;
            pSendData       =   NULL;
            pRecvData       =   NULL;
            pOneCommand     =   NULL;
    } }
      

  23.   

    不知道你有没有说明文档,你的这个猜的
    先打开串口,连接上设备 ->SendData 这样的吧,可能是某些步骤没有走,就直接发命令了。
    这同我上次做IF卡差不多。
    extern pFun_OpenComm pOpenComm; 
    extern pFun_bCommConnect pbCommConnect; 
    extern pFun_CloseComm pCloseComm; 
    extern pFun_SendData pSendData; 
    extern pFun_RecvData pRecvData; 
    extern pFun_OneCommand pOneCommand; 
      

  24.   

    不需要的.每个功能是单独的.你看看C的读身份卡的过程函数:也没有执行多余的调用,只要loadDll=>打开串口成功就可以读了:void CDemoVCDlg::OnButton5() 
    {
    //读身份证卡
        int nRet,i;
        CString ss,ss1;
        BYTE buf[2048];
        if(pOneCommand==NULL)
        {
            m_strEdit.Insert(0,"没有初始化通讯库\r\n");
            UpdateData(FALSE);
            return;
        }    nRet=pOneCommand(PICC_RDRead,0,buf,TYPE_ID2,1500);      //注意超时时间这里为1.5秒
        if(nRet>0)
        {
            ss="";
            for(i=0;i<nRet;i++)
            {
                ss1.Format("%02X ",buf[i]);
                ss+=ss1;
            }
            ss+="\r\n";
            m_strEdit.Insert(0,ss);
            if(buf[0]==0x00 && buf[1]==0x00 && buf[2]==0x90)    //一般只判断成功即可
            {
                //身份证读取成功,显示信息
                //前256字节为文本,后1024位加密压缩照片
                //文本
                char byName[32],bySex[4],byFolk[6],byBirth[18],byAddr[72],byIDNum[38],byDep[32],byBegin[18],byEnd[18];
                memset(byName   ,0,32);
                memset(bySex   ,0,4);
                memset(byFolk   ,0,6);
                memset(byBirth   ,0,18);
                memset(byAddr   ,0,72);
                memset(byIDNum   ,0,38);
                memset(byDep   ,0,32);
                memset(byBegin   ,0,18);
                memset(byEnd   ,0,18);
                int n;
                n=7;
                memcpy(byName,  &buf[ n],30);n+=30;
                memcpy(bySex ,  &buf[ n], 2);n+=2;
                memcpy(byFolk , &buf[ n], 4);n+=4;
                memcpy(byBirth, &buf[ n],16);n+=16;
                memcpy(byAddr,  &buf[ n],70);n+=70;
                memcpy(byIDNum, &buf[ n],36);n+=36;
                memcpy(byDep,   &buf[ n],30);n+=30;
                memcpy(byBegin, &buf[ n],16);n+=16;
                memcpy(byEnd,   &buf[ n],16);n+=16; ss=::SysAllocString((LPCWSTR)&byEnd);
    ss.TrimRight();
                m_strEdit.Insert(0,ss+"\r\n");
                ss=::SysAllocString((LPCWSTR)&byBegin);
    ss.TrimRight();
                m_strEdit.Insert(0,ss+"\r\n");
    ss=::SysAllocString((LPCWSTR)&byDep);
    ss.TrimRight();
                m_strEdit.Insert(0,ss+"\r\n");
    ss=::SysAllocString((LPCWSTR)&byIDNum);
    ss.TrimRight();
                m_strEdit.Insert(0,ss+"\r\n");
    ss=::SysAllocString((LPCWSTR)&byAddr);
    ss.TrimRight();
                m_strEdit.Insert(0,ss+"\r\n");
    ss=::SysAllocString((LPCWSTR)&byBirth);
    ss.TrimRight();
                m_strEdit.Insert(0,ss+"\r\n");
    ss=::SysAllocString((LPCWSTR)&byFolk);
    ss.TrimRight();
                ss=FOLK[atoi(ss.GetBuffer(ss.GetLength()))];
                m_strEdit.Insert(0,ss+"\r\n");
    ss=::SysAllocString((LPCWSTR)&bySex); //(CW2A((LPCWSTR)&bySex));
    ss.TrimRight();
                if(ss=="1")
    {
    ss="男";
    }
    else
    {
    ss="女";
    }
                m_strEdit.Insert(0,ss+"\r\n");
    ss=::SysAllocString((LPCWSTR)&byName);
    ss.TrimRight();
                m_strEdit.Insert(0,ss+"\r\n");
                UpdateData(FALSE);
                //照片,保存为文件
            if(m_hBitmap!=NULL)
                {
                    DeleteObject(m_hBitmap);
                }
        
                int nRet=0;
                FILE *fp;
                char filename[128];            //ss:=ExtractFilePath(Application.ExeName)+'b.bmp';
                TCHAR exePath[128];    
                GetModuleFileName(NULL,exePath,128);
                CString sPath;
                sPath.Format("%s",exePath);
                for(int i=sPath.GetLength();i>0;i--)
                {
                    if(exePath[i]==0x5c)
                    {
                        exePath[i+1]=0x00;
                        break;
                    }
                }
        
                sprintf(filename,"%szp.wlt",exePath);
                //保存文件
                fp=fopen(filename, "w+b");
                if( fp!=NULL )
                {
                fwrite(&buf[7+256],1024, 1, fp);
                fclose(fp);
                }
                else
                {
                    return;
                }
                //解码
            nRet=Ftest(filename);
                if(nRet==1)
                {
                    //读取文件显示
                    sprintf(filename,"%szp.bmp",exePath);
    m_hBitmap=(HBITMAP)LoadImage(NULL,filename,IMAGE_BITMAP,0,0,LR_CREATEDIBSECTION|LR_DEFAULTSIZE|LR_LOADFROMFILE);
                    if(m_hBitmap!=NULL )
                    {
                        m_ctBmp.SetBitmap(m_hBitmap);
                        m_ctBmp.ShowWindow(SW_SHOW);
                    }
                    else
                    {
                        m_ctBmp.ShowWindow(SW_HIDE);
                    }
                }
                else
                {
                     m_ctBmp.ShowWindow(SW_HIDE);
                     m_strEdit.Insert(0,"照片解码错误\r\n");
                }            m_strEdit.Insert(0,"读身份证卡成功\r\n");
            }
            else
            {
                m_strEdit.Insert(0,"读身份证卡失败\r\n");
            }
        }
        else
        {
            m_strEdit.Insert(0,"读身份证卡失败,未收到数据\r\n");
        }
        UpdateData(FALSE);
    }
      

  25.   

    或者说:ShowMessage((pbuff));  //这样试下。
    根本就读取不到OneCommand:function (cmd:Word;dlenth:word;var pbuff:array of AnsiChar;nTypeAb:word;nOutOfTime:word):Word;stdcall;我觉得很大程度上是  var pbuff:array of AnsiChar  定义的问题.
    因为执行这个过程后都能让读卡器Beep,这个是函数自动的.只要检测读取成功 就会Beep声响.关键是Beep后赋值给返回pbuff时就出现错误了.
    这种写法:var pbuff:array of AnsiChar  Delphi执行过程中不会报错,但是返回值为空.跟踪时发现  pbuff值根本没被改变.
    这种写法:
    OneCommand:function (cmd:Word;dlenth:word;pbuff:PAnsichar;nTypeAb:word;nOutOfTime:word):Word;stdcall;
    听到读卡器Beep后Delphi会出现错误.
      

  26.   

    搞定了,这个写法没想到能通过,并且能取值:var OneCommand:function (cmd: Integer; dLength: Integer; pBuff: PByte;
         nTypeAB: Integer; nOutOfTime: Integer): Integer; Stdcall;
      buf:array [0..2047] of BYTE ;
      iReturn:Integer;
    begin
      OneCommand := GetProcAddress(DllHandle,'OneCommand');
      try
        iReturn := OneCommand($3001,0, @buf[0], 1, 1500);
        if iReturn<0 then
        begin
          showmessage('OneCommand ERROR');
          Exit;
        end;
      finally  end;
    end;
      

  27.   

    有点意思,array[0..2047] of AnsiChar
    array[0..2047] of byte 是相同的。不明白,是不是你那个地方有地方错误。OK就行了。