我写了个dll,运行时会不定时出错,希望高手赐教。
//dll单元
unit U_dll_filter;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, Wwdatsrc, StdCtrls, Buttons;type
  TFm_filter = class(TForm)
    ComBox_field1: TComboBox;
    ...
    BitBtn_ok: TBitBtn;      //kind:bkok
    BitBtn_cancel: TBitBtn;  //kind:bkCancel
  end;function func_filter(ahandle:thandle;wwDsrc_filter:twwdatasource):string;StdCall;implementation{$R *.dfm}function func_filter(ahandle:thandle;wwDsrc_filter:twwdatasource):string;
var
  fm_filter:TFm_filter;
  filter_strlst:tstringlist;
  filter_str:string;
begin
  application.Handle:=ahandle;
  try
    fm_filter:=tfm_filter.Create(application);
    filter_strlst:=tstringlist.Create;
    filter_str:='';
    ...
    if fm_filter.ComBox_Field1.ItemIndex=0 then
    ...                        //do something
    result:=filter_str;
  finally
    fm_filter.Free;
  end;
end;end.
------------------------宿主程序单元
unit U_main;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, wwSpeedButton, wwDBNavigator, ExtCtrls, wwclearpanel,
  Grids, Wwdbigrd, Wwdbgrid, DB, Wwdatsrc, ADODB,WinTypes, WinProcs;type
  Tdata_filter = function (ahandle:thandle;wwDsrc_filter:twwdatasource):string;stdcall;
  EDLLLoadError = class(Exception);  TForm_main = class(TForm)
    ADOConnection1: TADOConnection;
    ADOTable1: TADOTable;
    wwDS_table: TwwDataSource;
    wwDBGrid1: TwwDBGrid;
    wwDBNavigator1: TwwDBNavigator;
    ...
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;var
  Form_main: TForm_main;implementation{$R *.dfm}procedure TForm_main.Button1Click(Sender: TObject);
var
  LibHandle   : THandle;
  data_filter:Tdata_filter;
begin
  LibHandle := LoadLibrary('filter_source.dll');
try
  if LibHandle = 0 then
    raise EDLLLoadError.Create('Unable to Load DLL');  @data_filter := GetProcAddress(LibHandle, 'func_filter');  if not (@data_filter = nil) then
  begin
    adotable1.Filter:=data_filter(application.Handle,wwDS_table);
    adotable1.Close;
    adotable1.Filtered:=true;
    adotable1.Open;
  endfinally
  FreeLibrary(LibHandle);
end;end.如果不把FreeLibrary(LibHandle)注释掉,运行一次就出错;注释掉,2至3次后出错。如果写作:
//dll单元
unit U_dll_filter;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, DB, Wwdatsrc, StdCtrls, Buttons;type
  TFm_filter = class(TForm)
    ComBox_field1: TComboBox;
    ...
    BitBtn_ok: TBitBtn;      //kind:bkok
    BitBtn_cancel: TBitBtn;  //kind:bkCancel
  end;function func_filter(ahandle:thandle;wwDsrc_filter:twwdatasource):string;export;implementation{$R *.dfm}function func_filter(ahandle:thandle;wwDsrc_filter:twwdatasource):string;
var
  fm_filter:TFm_filter;
  filter_strlst:tstringlist;
  filter_str:string;
begin
  application.Handle:=ahandle;
  try
    fm_filter:=tfm_filter.Create(application);
    filter_strlst:=tstringlist.Create;
    filter_str:='';
    ...
    if fm_filter.ComBox_Field1.ItemIndex=0 then
    ...                        //do something
    result:=filter_str;
  finally
    fm_filter.Free;
  end;
end;end.
------------------------宿主程序单元
unit U_main;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, wwSpeedButton, wwDBNavigator, ExtCtrls, wwclearpanel,
  Grids, Wwdbigrd, Wwdbgrid, DB, Wwdatsrc, ADODB,WinTypes, WinProcs;type  TForm_main = class(TForm)
    ADOConnection1: TADOConnection;
    ADOTable1: TADOTable;
    wwDS_table: TwwDataSource;
    wwDBGrid1: TwwDBGrid;
    wwDBNavigator1: TwwDBNavigator;
    ...
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  end;var
  Form_main: TForm_main;
  function func_filter(ahandle:thandle;wwDsrc_filter:twwdatasource):string;external 'P_dll_filter';
implementation{$R *.dfm}procedure TForm_main.Button1Click(Sender: TObject);
begin
    adotable1.Filter:=data_filter(application.Handle,wwDS_table);
    adotable1.Close;
    adotable1.Filtered:=true;
    adotable1.Open;
end;end.则可以运行多次,但超过3~4次后很容易出错。

解决方案 »

  1.   

    function func_filter(ahandle:thandle;wwDsrc_filter:twwdatasource):string;StdCall;
    的返回值要用pchar
      

  2.   

    如果不用Pchar,而用string的话要把sharemem这个单元作为dll工程文件的第一个引用文件,而宿主工程也要引用这个单元,并且也要作为第一个引用文件
    如果dll中包含了ado控件,要把ActiveX单元包含到dll工程中,并且在卸载dll时,要把所有的AdoQuery等关闭,否则报错
      

  3.   

    谢谢两位!
    如果我把BitBtn_ok的kind设为bkok,那么我点击这个按钮时,dll是否会自动释放form呢?
    我定义的tstringlist对象是否仍然必须手动释放?
      

  4.   

    To:dickeybird888(于伟刚)  "function func_filter(ahandle:thandle;wwDsrc_filter:twwdatasource):string;StdCall;
    的返回值要用pchar"能告诉我为什么吗?谢谢。