没有引用ShareMem单元.
uses
  ShareMem,//must be added here while your function or procedure
           //exported including string parameters
 SysUtils,
  Classes,
  windows,
  messages,
  graphics,
  forms,
  dialogs,
  mdi_unit in 'mdi_unit.pas' {Form2};

解决方案 »

  1.   

    同意楼上
    或者,改string为PChar
      

  2.   

    還是一樣出錯,我想可能時調用了dll后,沒有退出,一些值沒有還原的原因.因為如果不調dll就不會出錯.
      

  3.   

    不要传递Application对象,把Application.Handle传递进来:
    procedure loadchild(parentapphandle:HWND;parentcaption:string);export;stdcall;
    begin
    application.Handle:=parentapphandle;
    ...     ____     ____
         \ p \   / g /
          \ l \_/ n /
           \ a   o /
            \ i s /
             \ n /
              \_/
      

  4.   

    TO:plainsong
    根據你的提示修改程式后,可以正常退出了.可否說明其中是何道理呢?
    還有一點疑問:書上說動態調用DLL時要用loadlibrary,getprocaddress,freelibrary;現在我的程式中有用到前二個,freelibrary沒有用,一用就會出錯; 如果不用freelibrary會不會有其他問題? 如果要用,就以上的例子,如何用呢?
      

  5.   

    我在其它有关的贴子中也曾提过,在DLL中可以传递对象,但它的RTTI就不可用了.而VCL中的很多代码都用到了RTTI(这也是我对VCL不满意的一个地方),所以会出问题.
    改为传递Application.Handle后,传递的是一个全局(系统级)的句柄,然后你把它赋值给了DLL中的Application,这是DLL中的VCL对象,在DLL中用是没有问题的.
    总之,当使用DLL时,可以用VCL对象,但必须是自己的对象自己用,不要传递出去.
    至于FreeLibrary出错,我没有遇到过,建议在DLL中写一个ExitProc去调试一下.
      

  6.   

    我有在dll中寫一個exitproc,但退出dll時程序沒有執行這段;可否貼一個exitproc的例子給我看一下.
      

  7.   

    library Test;
    var  SaveExit: Pointer;procedure LibExit;begin
      ...  // library exit code
      ExitProc := SaveExit;  // restore exit procedure chain
    end;begin  ...  // library initialization code
      SaveExit := ExitProc;  // save exit procedure chain
      ExitProc := @LibExit;  // install LibExit exit procedure
    end.
      

  8.   

    還是沒有成功.
    程序的思路如下:在dll中放一個無模式(fsNormal)的form,通過主程序用動態調用的方法調用此form,dll中的form調用出來后,仍然可以切換到主程序(之前看的書上,dll中的form調出來后,主程序就不可使用了),退出時要釋放此dll;現在的問題是,退出時不知如何釋放此dll,我如果在主程序中加freelibrary
    (dllhandle),則調出的form會一閃就不見了;如果在dll中加exitproc,可退出時并沒有執行;所以我的程序中并沒有釋放dll的語句,這樣是不是有問題?是不是這种dll的調用方法有問題,不支持含無模式(fsNormal)的form的dll,但想一想應該不會;問題出在哪里呢?
      

  9.   

    在你的无模式窗体的OnClose事件中加上一行:
    Action := caFree;
    然后试一试:
    1.先关闭无模式窗体再卸载DLL
    2.不关闭无模式窗体卸载DLL.
    以前我也作过类似的工作,不过我作的是主窗体的POPUP窗体,主窗体关闭时它会自动被关闭.
      

  10.   

    不大明白你的意思.
    我的意思是何時卸载DLL及如何卸载DLL?如果不卸载DLL就關閉主程序,可不可以?因我的程序可以正常調用dll,也可以關閉dll中的form,也可以正常關閉主程序,只是沒有卸载DLL.>>現在的問題是,退出時不知如何釋放此dll,我如果在主程序中加freelibrary
    >>(dllhandle),則調出的form會一閃就不見了,當然主程序也可以正常關閉.
      

  11.   

    我的意思是说可能是因为在你调用FreeLibrary时有些在DLL中创建的窗体没有关闭,在DLL被卸载后,它还在接收消息,从而调用它的消息处理函数,而这个函数在DLL中,结果导致了内存访问异常.
      

  12.   

    我明白你的意思了.可能你會錯意了.
    現在我的程序或開或關不會出任何錯誤,主窗体关闭时dll中的form也会自动被关闭,無論已經調出了多少個dll中的form;只是主程序中沒有明確的語句卸载DLL.因為我如果在主程序中加freelibrary(dllhandle),則調出的form會一閃就不見了,即使這樣主程序關閉時出不會出錯.
    現在的問題是我不知何時卸载DLL及如何卸载DLL.
    我可將源程序傳給你,可以幫我看一看嗎?請留email給我.
      

  13.   

    我看了一下你的源代码,你的程序是不知道什么时候应该卸载DLL的,那么就应该在程序退出时卸载它,或不显示调用FreeLibrary.
    你可以这样作:
    写一个类处理这个DLL,在构造函数中加载,在析构函数中卸载,由使用者决定何时创建何时释放:
    unit MdiDllProxy;interfaceuses
      Windows,Classes,SysUtils;type  t_provachild = procedure(parentapplication:thandle;parentcaption:string);stdcall;  TMDIDLL = class(TObject)
      protected
        FLibrary:THandle;
        FLoadChild: t_provachild;0D
      public
        constructor Create(LibFileName:String);
        destructor Destroy;override;
        procedure LoadChild(parentapplication:thandle;parentcaption:string);
      end;implementation{ TMDIDLL }constructor TMDIDLL.Create(LibFileName: String);
    begin
      FLibrary := loadlibrary('mdidll');
      if FLibrary = 0 then
        raise Exception.CreateFmt('无法装载库文件:s',[LibFileName]);
      FLoadChild := getprocaddress(FLibrary,'loadchild');
      if not Assigned(FLoadChild) then
        raise Exception.CreateFmt('无法在库s上定位入口s',[LibFileName,'loadcheld']);
    end;destructor TMDIDLL.Destroy;
    begin
      inherited;
      if FLibrary <> 0 then
        FreeLibrary(FLibrary);
    0Aend;procedure TMDIDLL.LoadChild(parentapplication: thandle;
    0A  parentcaption: string);
    0Abegin
      if Assigned(FLoadChild) then
        FLoadChild(parentapplication,parentcaption);
    end;end.对于你这个程序来说,就应该这样用:
    ...
    uses MdiDllProxy;
    var
      MdiDLL:TMdIDLL;
    procedure TForm1.Button1Click(Sender: TObject);
    begin
      MdiDll.LoadChild(Application.Handle,'TestWindow');
    end;initialization
      MdiDLL := TMDIDLL.Create('mdidll.dll');//这段代码将在程序开始前运行.
    finalization
      MdiDLL.Free;//这段代码将在程序退出时运行.
    end.
      

  14.   

    謝謝.你的思路我明白了.但這种方法只適用于已知dll文件名的情況.因initialization
      MdiDLL := TMDIDLL.Create('mdidll.dll'),已固定了要調用dll文件;如果在主程序中調用不同的dll文件,則不適用;我傳給你的程序只是一個測試;我的整個思路是通過主程序中不同的菜單,調用不同的dll文件,從而實現不同的功能模塊;有沒有方法,可以在dll中的主form關閉時釋放dll?