大侠们给看看:
  TfrmA = class(TfrmB)
    btnSet: TBitBtn;  
  private
    I: Integer;
  public    
    procedure Test;    
  end;procedure TfrmATest; 
var 
  Handle1, Handle2: THandle;
begin
  XHandle := Self.Hanlde;
  I := 1;
  if I = 1 then
    GetX() //GetX为动态库函数
    Handle2 := Self.Handle;
  else
    ....;   调用之后: 
    此时 I 已经不为1了,而是一个很大的负数
    Handle1与Handle也不相等,为什么?
    
end;

解决方案 »

  1.   

    呃通常是动态库中的函数越界造成的你先把GetX都删除再调用试试看.
      

  2.   

    看一下GetX的调用规则或参数表对不对
    看起来像是堆栈中的Self指针被破坏了
      

  3.   

    GetX是动态载入,所传的参数应该没有问题。
      

  4.   

    function GetX(sParam:pchar;iParamLen:integer;sDataFormat:pchar;sBack:pchar): integer;stdcall;
      

  5.   

    你什么都不说,谁能给你搞定啊把DLL中GetX的实现或者调用规范的文档贴出来啊
      

  6.   

    我写的GetX实际为下面的AnalyseGetData ,它把动态库中的函数又封装了一下,如下所示:type
      TAnalyseGetData  = function(sParam:pchar;iParamLen:integer;sDataFormat:pchar;sBack:pchar): integer;stdcall;function AnalyseGetData(sParam:pchar;iParamLen:integer;sDataFormat:pchar): ReturnChar ;
    var
      iBack:integer;
      th:Thandle;
      anaData:TAnalyseGetData;
      tp:TFarProc;
      reChar:ReturnChar;
      i : integer;
      sBack : pchar;
    begin
        iBack := 0;
        th := LoadLibrary('.\645_1997.dll');
        if (th > 0) then
        begin
           try
             tp := GetProcAddress(th,'AnalyseGetData');
             if (tp <> nil) then
             begin
               anaData := TAnalyseGetData(tp);
               getMem(sBack,sizeof(pchar));
               iBack := anaData(sParam,iParamLen,sDataFormat,@sBack);
               reChar.iLen := iBack;
               if iBack > 0 then
                for i := 0 to iBack -1 do
                  reChar.sBack := reChar.sBack + sBack[i];
               //FreeMem(@sBack);
             end //if (tp <> nil) then
             else
             begin
               iback := 0;
               reChar.iLen := iBack;
               reChar.sBack := '';
             end;
           finally
             FreeLibrary(th);
           end;//try
        end;//if (th > 0) then
      result :=  reChar;
    end;
    调用:
         rec := AnalyseGetData(pchar(sBuffer),
                                4,
                                pchar(node.strings[6]));
      

  7.   

    1、ReturnChar的类型是什么?
    2、两个sBack,编译能通过?
    3、getMem(sBack,sizeof(pchar));字符串只要四个字节就够了?
    4、645_1997.dll中AnalyseGetData方法的实现或者调用规范是什么?
    5、for i := 0 to iBack -1 do reChar.sBack := reChar.sBack + sBack[i];用不着这么写
    6、代码你可以重写了
      

  8.   

    首先非常感谢lake_cx 耐心的看完代码,并提出多个疑问!其次要说明一下,这是我刚刚接手主管的一个程序,动态库内部实现我不知道,没有源码。其它待我逐一回答:1、ReturnChar的类型是什么?
    记录类型
    type
      ReturnChar = record
        iLen : integer;
        sBack: string;
    end;

     
    2、两个sBack,编译能通过? 
    没看到两个,编译无问题。 若你是指reChar.sBack := reChar.sBack + sBack[i]; 请看问题13、getMem(sBack,sizeof(pchar));字符串只要四个字节就够了? 
    此处似乎有待斟酌,我再仔细看看4、645_1997.dll中AnalyseGetData方法的实现或者调用规范是什么?
    无源码,
    C++声明为:
    函数定义 int AnalyseGetData(char *sParam,int iParamLen,char *sDataFormat,char *&sBack )
    函数用途 解析查询返回的报文
    参数 sParam:[输入量],查询返回的报文
    iParamLen:[输入量],报文长度
    sDataForamt:[输入量],数据格式
    sBack:[输出量],输出解析报文
    返回值 int,解析后的报文长度
    5、for i := 0 to iBack -1 do reChar.sBack := reChar.sBack + sBack[i];用不着这么写 
    直接这么写?reChar.sBack := sBack6、代码你可以重写了
    别人都用了很长时间了,最后考虑。
      

  9.   

    这个定义本身就是不对的(怎么没写WINAPI?最后一个参数应该是char *sBack才正确)
    int AnalyseGetData(char *sParam,int iParamLen,char *sDataFormat,char *&sBack)
    最后一个参数是返回一个char *,而不是传入一个char *让AnalyseGetData为其填充字符串
    因此对应的调用规范应该是
    function AnalyseGetData(sParam:pchar;iParamLen:integer;sDataFormat:pchar;var sBack:pchar): integer;stdcall;
    因此你只要申明一个PChar指针就可以了,AnalyseGetData会为字符串开辟一段内存,并写好数据,然后把地址写到你这个PChar指针中去,因此字符串数据是无法释放的,会导致内存泄露
      

  10.   

    谢谢lake_cx,根据你的意思,我做了如下调整,请指正。type 
      TAnalyseGetData  = function(sParam:pchar;iParamLen:integer;sDataFormat:pchar;var sBack:pchar): integer;stdcall; function AnalyseGetData(sParam:pchar;iParamLen:integer;sDataFormat:pchar): ReturnChar ; 
    var 
      iBack:integer; 
      th:Thandle; 
      anaData:TAnalyseGetData; 
      tp:TFarProc; 
      reChar:ReturnChar; 
      i : integer; 
      sBack : pchar; 
    begin 
        iBack := 0; 
        th := LoadLibrary('.\645_1997.dll'); 
        if (th > 0) then 
        begin 
          try 
            tp := GetProcAddress(th,'AnalyseGetData'); 
            if (tp <> nil) then 
            begin 
              anaData := TAnalyseGetData(tp); 
              //getMem(sBack,sizeof(pchar)); 去掉分配内存
              iBack := anaData(sParam,iParamLen,sDataFormat,sBack); 
              reChar.iLen := iBack; 
              if iBack > 0 then    
                reChar.sBack := sBack;   //直接赋值        
            end //if (tp <> nil) then 
            else 
            begin 
              iback := 0; 
              reChar.iLen := iBack; 
              reChar.sBack := ''; 
            end; 
          finally 
            FreeLibrary(th); 
          end;//try 
        end;//if (th > 0) then 
      result :=  reChar; 
    end; 
    调用: 
        rec := AnalyseGetData(pchar(sBuffer), 
                                4, 
                                pchar(node.strings[6])); 
      

  11.   

    只差lake_cx 最后确认的一步,怎么看不到人了呢
      

  12.   

    按照你说的,应该就是这么调用,我还以为你试过了没问题呢(有问题早就说出来了)
    PS:LoadLibrary中用相对路径不保险;貌似ReturnChar中的iLen是多于的,string中第一个字节就是它的长度
      

  13.   

    我用改过测试的结果同样如此 I := -1982713088;当然动态库函数我还没改成int AnalyseGetData(char *sParam,int iParamLen,char *sDataFormat,char *sBack )形式 ,我没有源码。等拿到源码我再试试。十分感谢lake_cx !如果需要,可能还找你讨论。