我新建立一个工程,调用一funDLL(不含Form),静态调用,完全没问题。我的主程序调用一个moDLL(含Form),再用moDll去调用此funDLL,同样的调用方法,同样的函数,调用出现内存错误。
难道我的主程序调用moDll的时候有误??我的调用方法传入了Application的handle,传入了Application的ICon。
另外没什么特殊的地方,moDLL一直使用没啥问题,这次为了新增的一个功能
调用了这个funDll却出现内存错误请各位指点指点。

解决方案 »

  1.   

    换了几种调用DLL的方法,还是没有解决,郁闷中...
      

  2.   

    调用部分:
          sDoorRes:=LoadDllDOMakeDoorCard(PChar(RComm.HOTELDoorStyle)
            ,PChar(RComm.HOTELAddRoomPriceTime)
            ,PChar(adsRoomOrder.FieldByName('F_KeyId').AsString)
            ,Trunc(Now)+1,Self);LoadDllDOMakeDoorCard函数内容:
    function  LoadDllDOMakeDoorCard(sDoorLockType,sEndTime,aRoomNo:PChar;sEndDate:TDateTime;
      fOwer:TForm):string;
    var RunDLL : function (aApp: TApplication;Scr: TScreen;pDoorLockType,pEndTime,pRoomNo,
      pComIndex,pLastingTime,pLockRegStr:PChar;sEndDate:TDateTime;
      aAConn:TADOConnection;fOwer:TForm):PChar;stdcall;
    var
      GetDllHWND: HWND;
    begin
      GetDllHWND := LoadLibrary(PChar('OLDNetLock.dll'));
      try
        if GetDllHWND < 32 then
        begin
          MessageBox(0, '没有找到附带DLL文件,请确认程序是否完整!',
            '加载DLL失败', MB_OK);
          Exit;
        end;
        RunDLL := GetProcAddress(GetDllHWND, 'RunDLL');
        try
          Result:=RunDLL(Application,Screen,PChar(sDoorLockType)
          ,PChar(sEndTime),PChar(aRoomNo),PChar(RComm.HOTELDoorCom)
          ,PChar(RComm.HOTELDoorLastingTime)
          ,PChar(RComm.HOTELDoorCode),sEndDate,RComm.InCon,fOwer);
        except
        end;
      finally
        FreeLibrary(GetDllHWND);
      end;
    end;
    DLL部分:
    library OLDNetLock;
    uses
      ExceptionLog,
      SysUtils,
      Classes,
      Controls,
      ADODB,
      Forms,
      Windows,
      Dialogs,
      zNetLock60 in 'zNetLock60.pas' {frmNetLock60},
      zNetLock60IC in 'zNetLock60IC.pas' {frmNetLock60IC};
    var DLLApp: TApplication; DLLScreen: TScreen;function RunDLL(aApp: TApplication;Scr: TScreen;pDoorLockType,pEndTime,pRoomNo,
      pComIndex,pLastingTime,pLockRegStr:PChar;sEndDate:TDateTime;
      aAConn:TADOConnection;fOwer:TForm):PChar;stdcall;
    var aFormNetLock60IC: TfrmNetLock60IC;
      PrjACon:TADOConnection;
    begin
      Application := aApp;
      Screen := Scr;
      Result:='';
      PrjACon:=TADOConnection.Create(nil);
      try
        PrjACon:=aAConn;
        aFormNetLock60IC := TfrmNetLock60IC.Create(nil);
        with  aFormNetLock60IC do begin
        try
          sComIndex:=pComIndex;
          sLastingTime:=pLastingTime;
          sLockRegStr:=pLockRegStr;
          adsCardSet.Connection :=PrjACon;
          dtedtEndCard.Date :=Trunc(sEndDate);
          teEndCard.Time := StrToDateTime(pEndTime);
          LedPreview.Caption :=pRoomNo+' OPEN DOORCARD';
          lbl1.Caption :=pRoomNo;
          Caption :='<'+pDoorLockType+'>'+' 正在制作'+pRoomNo+'门卡,请稍等...';
          if ShowModal=mrOk then
              Result:=PChar(FormatDateTime('YYYY-MM-DD HH:MM'
                ,Int(dtedtEndCard.Date)+Frac(teEndCard.Time)))
          else Result:='';
        finally
          FreeAndNil(aFormNetLock60IC);
        end;
        end;
        PrjACon.Close;
      finally
        PrjACon.Free;
      end;
    end;procedure DLLUnloadProc(dwReason: DWORD);
    begin
      if dwReason = DLL_PROCESS_DETACH then
      begin
        Application := DLLApp; //恢复
        Screen := DLLScreen;
      end;
    end;exports RunDLL;begin
      DLLApp := Application;  
      DLLScreen := Screen;
      DLLProc := @DLLUnloadProc;  
      DLLUnloadProc(DLL_PROCESS_DETACH);
    end.
      

  3.   

    DLL中 TfrmNetLock60IC 声明调用funDLL函数部分
      const dllname='网讯6.0(IC)\T5557.dll';
      FUNCTION PortOpen_IC(port:Word):LongWord;STDCALL;external dllname;
      Function PortClose_IC(icdev : LongWord) :Word;STDCALL;external dllname;
      Function Clear_Card_IC(icdev : LongWord) : Word;STDCALL;external dllname;
      Function CardCode(var CARD_CODE : Byte):word;STDCALL;external dllname;
      Function dv_beep  ( icdev : LongWord; time : Word) :Word;
        STDCALL;external '网讯6.0(IC)\Mwic_32.dll';
      Function Guest_Card_IC(icdev : LongWord;var Authorization_Code : Byte
        ; var CardID : Byte; var Room1 : Byte
        ; var Room2 : Byte; var Room3 : Byte; var Start_Time : Byte; var End_Time : Byte)
        : Word;STDCALL;external dllname;调用:
    var   port : Word;  st : Longword;
    begin
      port :=StrToInt(sComIndex); //COM4  COM1为0  sComIndex,sLastingTime,sLockRegStr
      st:=0;
      try
        st := PortOpen_IC(port);
        dv_beep(st,10);
      except on e:Exception do
        ShowMessage('error:'+e.Message);
      end;
      If st > 0 Then begin
        commdev := st;
      end Else begin
          ShowMessage('连接读写器错误!');
          commdev := 0;
      end;
    end;这个过程会出现内存错误。
      

  4.   

    如果我用一个新创建的工程去调用TfrmNetLock60IC  
    同样的声明方法
      const dllname='网讯6.0(IC)\T5557.dll';
      FUNCTION PortOpen_IC(port:Word):LongWord;STDCALL;external dllname;
      Function PortClose_IC(icdev : LongWord) :Word;STDCALL;external dllname;
      Function Clear_Card_IC(icdev : LongWord) : Word;STDCALL;external dllname;
      Function CardCode(var CARD_CODE : Byte):word;STDCALL;external dllname;
      Function dv_beep  ( icdev : LongWord; time : Word) :Word;
        STDCALL;external '网讯6.0(IC)\Mwic_32.dll';
      Function Guest_Card_IC(icdev : LongWord;var Authorization_Code : Byte
        ; var CardID : Byte; var Room1 : Byte
        ; var Room2 : Byte; var Room3 : Byte; var Start_Time : Byte; var End_Time : Byte)
        : Word;STDCALL;external dllname;调用:
    var   port : Word;  st : Longword;
    begin
      port :=StrToInt(sComIndex); //COM4  COM1为0  sComIndex,sLastingTime,sLockRegStr
      st:=0;
      try
        st := PortOpen_IC(port);
        dv_beep(st,10);
      except on e:Exception do
        ShowMessage('error:'+e.Message);
      end;
      If st > 0 Then begin
        commdev := st;
      end Else begin
          ShowMessage('连接读写器错误!');
          commdev := 0;
      end;
    end;很正常,不会出错。
      

  5.   

    一种可能性是传出的PChar是dll空间的,在FreeLibrary的时候会被释放掉,静态调用FreeLibrary执行的晚,此时string已经没在使用了,把错误掩盖了。理论上PChar到string的赋值会拷贝内存,但实际执行中好像有不拷贝直接引用的情况(短string还是长string,忘记了)。另一种可能性是传入的TApplication和TForm的问题。理论上这种传对象应当完全禁止,而改为传Handle。
      

  6.   

    哦,谢谢。我马上改传form为form的Handle关键是主程序调用我写的DLL不会存在错误,而使用我的主程序调用我写的那个DLL,再由此DLL去静态调用T5557.dll时会出现内存错误。如果不执行下面Dll中调用DLl的那个过程,我写的那个DLL调用没有报出任何错误。
    var   port : Word;  st : Longword;
    begin
      port :=StrToInt(sComIndex); //COM4  COM1为0  sComIndex,sLastingTime,sLockRegStr
      st:=0;
      try
        st := PortOpen_IC(port);
        dv_beep(st,10);
      except on e:Exception do
        ShowMessage('error:'+e.Message);
      end;
      If st > 0 Then begin
        commdev := st;
      end Else begin
          ShowMessage('连接读写器错误!');
          commdev := 0;
      end;
    end;
    而这个问题奇怪就在于,如果新建一个新的工程去调用此T5557.dll中的函数,不会有任何错误。
      

  7.   

    ---------------------------
    Reception
    ---------------------------
    error:Access violation at address 05F55B20. Write of address 00000000
    ---------------------------
    OK   
    ---------------------------
      

  8.   

    PortOpen_IC(port); 就出现内存错误