问题解决倾分相送 
体情况说明
1.delphi中声明如下
function getdata(l_cominfoU1a,l_cominfoU1b,l_cominfoU2a,l_cominfoU2b,l_cominfoU3a,l_cominfoU3b,l_cominfoU4:Longint;strdata,errmessage:pchar):Longint stdcall;external 'KCM.dll';
//前7参数为usb端口号句柄,后面参数“strdata:是要传给dll的处理的原始数据串,errmessage是截获的错误信息;函数返回值是整型2.vc 写的dll (用vb调用通过不会报任何错误)
vc 代码 程序如下:
extern "C" unsigned short pascal getdata(HANDLE fd1,HANDLE fd2,HANDLE fd3,HANDLE fd4,HANDLE fd5,HANDLE fd6,HANDLE fd7,unsigned char *Data,unsigned char *message)
{
unsigned short ret;
/************************************************************************************/ //fd1复位
    if ((ret=icc_reset(fd1)!=0x9000)//函数icc_reset探测有没有端口有没有插入usb设备的函数有则返回0x9000,无则报其他错误(如ox6805)
{strcpy((char *)message,"USB 1: 复位"); strcat((char *)message,"\x0"); return ret;} //fd2复位
    if ((ret=icc_reset(fd2)!=0x9000)
{strcpy((char *)message,"USB 2: 复位"); strcat((char *)message,"\x0"); return ret;} //fd3复位
    if ((ret=icc_reset(fd3)!=0x9000)
{strcpy((char *)message,"USB 3: 复位"); strcat((char *)message,"\x0"); return ret;}

//fd4复位
    if ((ret=icc_reset(fd4)!=0x9000)
{strcpy((char *)message,"USB 4: 复位"); strcat((char *)message,"\x0"); return ret;}

//fd5复位
    if ((ret=icc_reset(fd5)!=0x9000)
{strcpy((char *)message,"USB 5: 复位"); strcat((char *)message,"\x0"); return ret;}

//fd6复位
    if ((ret=icc_reset(fd6)!=0x9000)
{strcpy((char *)message,"USB 6: 复位"); strcat((char *)message,"\x0"); return ret;}

//fd7复位
    if ((ret=icc_reset(fd7)!=0x9000)
{strcpy((char *)message,"USB 7: 复位"); strcat((char *)message,"\x0"); return ret;}

{处理跟usb数据通信的部分}
return ret;
}用delphi调用能获得返回值0x9000 但是再运行下去就报无效指针错误或内存错误。dll应该没问题用vb程序调用测试通过,一且正常。
因为是vc写得所以dll也无法加sharemem。
请各位大虾指点,小弟不才 数全给了以报答谢之恩。

解决方案 »

  1.   

    补充: 参数strdata:申明的时候为pchar 类型或者申明的时候是string型,传进去的时候pchar(strdata),都试过了,函数都能获得返回值,但是都报内存错或无效指针操作;很烦啊,各位先进 真的麻烦你们了 
      

  2.   

    1.楼主说的"用delphi调用能获得返回值0x9000 ", 你是自己在Delphi中调试看到的返回值么?
    2.楼书说的"但是再运行下去就报无效指针错误或内存错误。"是什么意思? 调用DLL函数的语句正确,但下一步就错误了? 不明白你说的是什么情况下出的错.你可以把调用的部分拿出来,然后说运行到哪一步时出什么错了.
      

  3.   

    1.delphi中声明如下 
    function getdata() stdcall;vc 代码 程序如下: 
    extern "C" unsigned short pascal getdata()兄弟,stdcall与pascal 不协调,二者对参数的压栈顺序不一样:
    stdcall    按从右至左的顺序压参数入栈
    pascal     按从左至右的顺序压参数入栈 ...其它的与_stdcall相同;
      

  4.   

    delphi中声明如下 
    function getdata(l_cominfoU1a,l_cominfoU1b,l_cominfoU2a,l_cominfoU2b,l_cominfoU3a,l_cominfoU3b,l_cominfoU4:Longint;strdata,errmessage:pchar):Longint pascal;external 'KCM.dll'; 把stdcall 改为 pascal 就可以了
      

  5.   

    回复:ppluming 
    返回值是调试跟踪观察的。
    后面函数如下       if ierr=$9000 then
          begin
             SB.Panels[0].Text:='检查完毕!';
             showmessage('OK') ;
           try          ct_close(l_cominfoUSB1);
              ct_close(l_cominfoUSB2);
              ct_close(l_cominfoUSB3);
              ct_close(l_cominfoUSB4);        except
            end;
          end
          else
          begin
            SB.Panels[0].Text:='发行失败!';
            try
              ct_close(l_cominfoUSB1);
              ct_close(l_cominfoUSB2);
              ct_close(l_cominfoUSB3);
              ct_close(l_cominfoUSB4);
            except
            end;
          end;
    调试发现只要对窗体或某个控件赋值或显示举报错,或程序推出!
           如:
        SB.Panels[0].Text:='检查完毕!';

             showmessage('OK') ;
    就报错。
    把这两行都去掉,则是报错的地方是 跟踪完成 再显示窗体的时候错误。窗体hook什么的报错。
      

  6.   

    Delphi当中的pascal和Microsoft在win32当中声明的Pascal是有区别的,前者还是Pascal,后者实际上是通常说的stdcall,具体的可以参阅MSDN.
      

  7.   

    回复xiaoxiao_8 :刚试过,调试中 返回值都得不到就报内存错了。谢谢你。
      

  8.   

    我按僵哥的意思,這樣改下:
    errmessage:array[0..1023] of char
     或者 GetMem(ErrMessage,1023);
      然後再調用函數
      

  9.   

    内存分配了,我在公共变量中都分配了 
    并且都获得了值再传给要调用getdata函数的,谢谢你。
      

  10.   

    大虾们,我跟踪调试发现用stdcall能得到返回值ox9000,只是后面总报错。比如    SB(Statebar).Panels[0].Text:='检查完毕!'; 
    或 
            showmessage('OK') ;  而用pascal 调试获得不了值,并且函数还没跳出来就报错了。
    谢谢两位了。
      

  11.   


    回复:
    大虾们,我跟踪调试发现用stdcall能得到返回值ox9000,只是后面总报错。比如    SB(Statebar).Panels[0].Text:='检查完毕!'; 
    或 
            showmessage('OK') ;  而用pascal 调试获得不了值,并且函数还没跳出来就报错了。 
    谢谢两位了
      

  12.   


    刚才试了,不行能获得返回值,但是还是老问题,运行到SB.Panels[0].Text:='检查完毕!';就报错。谢谢你!
      

  13.   

    procedure TForm1.Button1Click(Sender: TObject);
    var
      strTMP   :string;
      ierr  :Integer;
      errmessage,strdata:PChar;
    begin   button1.Enabled:=false;
       strdata:=PChar(Edit1.Text);
      if strdata='' then
      begin
        Application.MessageBox(PChar('传递数据不能为空!'),'信息提示',MB_OK+MB_ICONERROR);
        Exit;
      end else
      begin
        strtmp:='';
        strtmp:= CheckUSB ;//返回值为string 检查是否都有插入usb设备,如果都有则返回空,否则返回具体信息
                              //通过这个函数获得usb的各个端口句柄值(本窗体公共变量),供传给getdata函数用
        if  strtmp<>'' then
        begin
          Application.MessageBox(PChar(strtmp),'信息提示',MB_OK+MB_ICONERROR);
          Exit;
        end  else   //调用动态库函数
        begin
          try
           flag:='0101010';
           ierr:=$9000;
          // GetMem(ErrMessage,1023);
            SB.Panels[0].Text:='正在通信...';
            screen.Cursor:=crHourGlass;
            ierr:=Issue(l_cominfoUSB1,l_cominfoUSB1,l_cominfoUSB2,l_cominfoUSB2,l_cominfoUSB3,l_cominfoUSB3,l_cominfoUSB4,strdata,errmessage);
          finally
            screen.Cursor:=crdefault;
            button1.Enabled:=true;
          end;
          if ierr=$9000 then
          begin
           try
             SB.Panels[0].Text:='检查完毕!'; //程序一般在这报错
              showmessage('OK') ;   //注释掉上行则本行报错
              ct_close(l_cominfoUSB1);//关闭端口
              ct_close(l_cominfoUSB2);
              ct_close(l_cominfoUSB3);
              ct_close(l_cominfoUSB4);        except
            end;
          end
          else
          begin
            SB.Panels[0].Text:='通信失败!';
            try
              ct_close(l_cominfoUSB1);
              ct_close(l_cominfoUSB2);
              ct_close(l_cominfoUSB3);
              ct_close(l_cominfoUSB4);
            except
            end;
          end;
        end;
      end;
    end;
      

  14.   


    I补充 issue 函数 就是getdata函数
      

  15.   

    ------------------dll中 getdata 函数如下:--------------extern "C" unsigned short pascal getdata(HANDLE fd1,HANDLE fd2,HANDLE fd3,HANDLE fd4,HANDLE fd5,HANDLE fd6,HANDLE fd7,unsigned char *Data,unsigned char *message) 

    unsigned short ret; 
    //fd1复位 
        if ((ret=icc_reset(fd1)!=0x9000)//函数icc_reset探测有没有端口有没有插入usb设备的函数有则返回0x9000,无则报其他错误(如ox6805) 
    {strcpy((char *)message,"USB 1: 复位"); strcat((char *)message,"\x0"); return ret;} //fd2复位 
        if ((ret=icc_reset(fd2)!=0x9000) 
    {strcpy((char *)message,"USB 2: 复位"); strcat((char *)message,"\x0"); return ret;} //fd3复位 
        if ((ret=icc_reset(fd3)!=0x9000) 
    {strcpy((char *)message,"USB 3: 复位"); strcat((char *)message,"\x0"); return ret;} //fd4复位 
        if ((ret=icc_reset(fd4)!=0x9000) 
    {strcpy((char *)message,"USB 4: 复位"); strcat((char *)message,"\x0"); return ret;} //fd5复位 
        if ((ret=icc_reset(fd5)!=0x9000) 
    {strcpy((char *)message,"USB 5: 复位"); strcat((char *)message,"\x0"); return ret;} //fd6复位 
        if ((ret=icc_reset(fd6)!=0x9000) 
    {strcpy((char *)message,"USB 6: 复位"); strcat((char *)message,"\x0"); return ret;} //fd7复位 
        if ((ret=icc_reset(fd7)!=0x9000) 
    {strcpy((char *)message,"USB 7: 复位"); strcat((char *)message,"\x0"); return ret;} {处理跟usb数据通信的部分} 略去(只保留判断是否有端口设备不处理数据),
    return ret; 
    } --------------------------delphi中 过程如下-----------------------procedure TForm1.Button1Click(Sender: TObject); 
    var 
      strTMP  :string; 
      ierr  :Integer; 
      errmessage,strdata:PChar; 
    begin   button1.Enabled:=false; 
      strdata:=PChar(Edit1.Text); 
      if strdata='' then 
      begin 
        Application.MessageBox(PChar('传递数据不能为空!'),'信息提示',MB_OK+MB_ICONERROR); 
        Exit; 
      end else 
      begin 
        strtmp:=''; 
        strtmp:= CheckUSB ;//返回值为string 检查是否都有插入usb设备,如果都有则返回空,否则返回具体信息 
                              //通过这个函数获得usb的各个端口句柄值(本窗体公共变量),供传给getdata函数用 
        if  strtmp <>'' then 
        begin 
          Application.MessageBox(PChar(strtmp),'信息提示',MB_OK+MB_ICONERROR); 
          Exit; 
        end  else  //调用动态库函数 
        begin 
          try 
          flag:='0101010'; 
          ierr:=$9000; 
          // GetMem(ErrMessage,1023); 
            SB.Panels[0].Text:='正在通信...'; 
            screen.Cursor:=crHourGlass; 
            ierr:=getdata(l_cominfoUSB1,l_cominfoUSB1,l_cominfoUSB2,l_cominfoUSB2,l_cominfoUSB3,l_cominfoUSB3,l_cominfoUSB4,strdata,errmessage); //调用dll中 函数
          finally 
            screen.Cursor:=crdefault; 
            button1.Enabled:=true; 
          end; 
          if ierr=$9000 then 
          begin 
          try 
            SB.Panels[0].Text:='检查完毕!'; //程序一般在这报错 
              showmessage('OK') ;  //注释掉上行则本行报错 
              ct_close(l_cominfoUSB1);//关闭端口 
              ct_close(l_cominfoUSB2); 
              ct_close(l_cominfoUSB3); 
              ct_close(l_cominfoUSB4);         except 
            end; 
          end 
          else 
          begin 
            SB.Panels[0].Text:='通信失败!'; 
            try 
              ct_close(l_cominfoUSB1); 
              ct_close(l_cominfoUSB2); 
              ct_close(l_cominfoUSB3); 
              ct_close(l_cominfoUSB4); 
            except 
            end; 
          end; 
        end; 
      end; 
    end;
    谢谢你 现在不知道怎么办,你看还不要什么要提供的?
      

  16.   


    没调试过你这个程序,现在只能是猜;
    strdata:=PChar(Edit1.Text); 
    这一句没分配内存,
    getdata(l_cominfoUSB1,l_cominfoUSB1,l_cominfoUSB2,l_cominfoUSB2,l_cominfoUSB3,l_cominfoUSB3,l_cominfoUSB4,strdata,errmessage)中的strdata有可能调用出错了。
    你改一下试试:
    var strdata:array[0..1023] of char;
    edit1.GetTextBuf(strdata,1024);
      

  17.   

    显然是传了个野指针进去啊,编译器应该会提示errmessage还没有初始化的啊
      

  18.   


    1、要是标准win32 DLL
    2、errmessage 传递的是一个野指针
    3、尝试一下先释放USB口,完成DLL中的操作后再设置UI界面。
      

  19.   

    指针不合法吧!
    换个类型,STRINGBULDIER看看行不。
      

  20.   

    不知道是不是这种问题。
    http://blog.donews.com/keo321/archive/2008/07/17/1321048.aspx以前用VC写的ATL控件也是出现指针错误,用vb,C#侧过没有问题,就是delphi调用时有问题。后来在 delphi中设置 Delphi:  const    MCW_EM = DWord($133f); 
     begin   
     Set8087CW(MCW_EM); 
     end;
    才解决了,试试看!
      

  21.   

    问题解决 ! 因为 strdata是pchar类型 ,所以 在 strdata:=PChar(Edit1.Text); 和 flag:=pchar(‘010101’),给 dll中 对 strdata操作埋下隐患 。因为 string类型 最后 一个 字符是空的null,所以 容易造成无效指针操作错误。谢谢各位大哥 。现在结贴。
    衷心感谢 :xiaoxiao_8 
      

  22.   

    正好遇到这个问题,多谢xiaoxiao_8 解惑
      

  23.   

    本人也刚遇到了这个,问题,根据xiaoxiao_8的提示解决了问题,再次感谢!!