//程序运行时,调用DLL没问题,调用完了,释放的时候总是出错:错误提示地址:000000000001不能为读!
//DLL内部程序
library Pshowcalendar;{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }uses
  sharemem,
  SysUtils,
  Classes,
  UDllFrm in 'UDllFrm.pas' {DllFrm};{$R *.res}
exports
  showcalendar,
  closecalendar;
begin
end.
//DLL内部的窗体PAS
unit UDllFrm;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, ExtCtrls;type
  TDllFrm = class(TForm)
    Panel1: TPanel;
    caldllcalendar: TMonthCalendar;
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormDestroy(Sender: TObject);
    procedure caldllcalendarDblClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }  end;
function showcalendar(ahandle: THandle; acaption: string): TDateTime;
stdcall;
procedure closecalendar(aformref: longint); stdcall;var
  DllFrm: TDllFrm;
implementationprocedure closecalendar(aformref: longint); stdcall;
begin
  if aformref > 0 then
    TDllFrm(aformref).Free;
end;function showcalendar(ahandle: THandle; acaption: string): TDateTime; stdcall;
var
  dllform: TDllFrm;begin  { //这段代码用于模式窗体。
  Application.Handle := ahandle;
   dllform := TDllFrm.Create(Application);
   try
     dllform.Caption := acaption;
     dllform.ShowModal;
     Result := dllform.caldllcalendar.Date;
   finally
     dllform.Free;
   end;
                  }//下面是用于非模式窗体。
  Application.Handle := ahandle;
  dllform := TDllFrm.Create(Application);
  Result := longint(dllform);
  dllform.Caption := acaption;
  dllform.Show;
end;{$R *.dfm}procedure TDllFrm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;
end;procedure TDllFrm.FormDestroy(Sender: TObject);
begin
  self := nil;
end;procedure TDllFrm.caldllcalendarDblClick(Sender: TObject);
begin
  Close;
end;end.
//外部调用DLL的程序:
unit Umain;interfaceuses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;type
  tshowcalendar = function(ahandle: THandle; acption: string): TDateTime;
  stdcall;
  edllloaderror = class(exception);  TMainForm = class(TForm)
    btngetcalendar: TButton;
    lbldate: TLabel;
    procedure btngetcalendarClick(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;var
  MainForm: TMainForm;implementation{$R *.dfm}procedure TMainForm.btngetcalendarClick(Sender: TObject);
var
  libhandle: THandle;
  showcalendar: tshowcalendar;begin
  libhandle := loadlibrary('Pshowcalendar.dll');
  try
    if libhandle = 0 then
      raise edllloaderror.Create('unable to load dll');
    @showcalendar := GetProcAddress(libhandle, 'showcalendar');
    if not (@showcalendar = nil) then
      lbldate.Caption := DateToStr(showcalendar(Application.Handle, Caption))
    else
      raiselastwin32error;
  finally
    // ShowMessage(IntToStr(libhandle));
    // freelibrary(libhandle);
    //FreeLibraryAndExitThread(libhandle, 0);
    //Application.Free ;
    //Application.Destroy;
    begin
      FreeLibrary(libhandle);
      //Application.Terminate;
    end;  end;
end;procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Action := caFree;end;procedure TMainForm.FormDestroy(Sender: TObject);
begin
  self := nil;
end;end.
//注:每次运行到freelibrary()的时候出错!就是这个地方的错!