全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:2898
推到 Plurk!
推到 Facebook!

載入dll退出程式時發生錯誤?

尚未結案
jeffxx
一般會員


發表:7
回覆:22
積分:5
註冊:2003-10-10

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-08-05 21:00:54 IP:220.135.xxx.xxx 未訂閱
請教一下各位前輩 我用了兩個方法去載dll但不知為什麼退出都會發生error 我在dll中寫了一個類別然後再寫一個funciton給主程式呼叫產生他的實體 不知道是不是這樣出了問題還是有其它的我沒處理好 ps:我是執行方法一or方法二再去run play stop 退出時出錯    
 
(1)主程式
unit Unit1;    interface    uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, StrUtils;
type      TPlayer = class
  private
  public
    procedure Paly(Display: TEdit; hAPP: Tapplication); virtual; abstract;
    procedure Stop(); virtual; abstract;
    function PlayerNmae: string; virtual; abstract;
    function GetInstance: TObject; virtual; abstract;
  end;      TForm1 = class(TForm)
    editDisplay: TEdit;
    btnPlay: TButton;
    btnStop: TButton;
    Button1: TButton;
    Button2: TButton;
    procedure btnPlayClick(Sender: TObject);
    procedure btnStopClick(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    myPlayer: TPlayer;
    { Public declarations }
  end;      TGetPluginInstance = function():TPlayer; Stdcall;
  function GetPluginInstance:TPlayer;stdcall;external 'plugin.dll';    var
  Form1: TForm1;
  hDLL: THandle;
implementation    {$R *.dfm}    procedure TForm1.btnPlayClick(Sender: TObject);
begin
  myPlayer.Paly(Form1.editDisplay,Application);
end;    procedure TForm1.btnStopClick(Sender: TObject);
begin
  myPlayer.Stop;
end;    procedure TForm1.FormDestroy(Sender: TObject);
begin
 Freeandnil(myPlayer);
 FreeLibrary(hDLL);
end;
//第一種載入方法
procedure TForm1.Button1Click(Sender: TObject);
var
  hDLL: THandle;
  pGetPluginInstance: TGetPluginInstance;
begin
  hDLL := LoadLibrary(PChar('plugin.dll'));
  if hDLL > 0 then
  begin
    @pGetPluginInstance := GetProcAddress(hDLL, 'GetPluginInstance');
    myPlayer := pGetPluginInstance;
  end else
  begin
    showmessage('loadfail');
  end;
end;
//第二種載入方法
procedure TForm1.Button2Click(Sender: TObject);
begin
  myPlayer:=GetPluginInstance;
end;
end.
發表人 - jeffxx 於 2005/08/05 21:04:19
jeffxx
一般會員


發表:7
回覆:22
積分:5
註冊:2003-10-10

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-08-05 21:01:53 IP:220.135.xxx.xxx 未訂閱
(2)dll內容
//=======================
library Project1;
uses
  SysUtils,
  Classes,
  Unit2 in 'Unit2.pas';    {$R *.res}
exports
  GetPluginInstance index 1;
begin
end.
//========================
unit Unit2;    interface    uses
 StdCtrls,Classes,windows,Messages,ShareMem,Forms;    type
  TPlayer=class
  private
  public
   procedure Paly(Display:TEdit;hAPP:Tapplication);virtual; abstract;
   procedure Stop();virtual; abstract;
   function PlayerNmae:String;virtual;abstract;
   function GetInstance:TObject;virtual; abstract;
  end;      TFilePlayer=class(TPlayer)
  private
   procFlag:Boolean;
  public
   procedure Paly(Display:TEdit;hAPP:Tapplication);override;
   procedure Stop();override;
   function PlayerNmae:String;
   function GetInstance:TObject;
  end;      function GetPluginInstance: TFilePlayer;stdcall;export;    implementation    function GetPluginInstance: TFilePlayer;stdcall;
begin
 Result:=TFilePlayer.Create;
end;    function TFilePlayer.GetInstance: TObject;
begin
 Result:=self.Create;
end;    procedure TFilePlayer.Paly(Display:TEdit;hAPP:Tapplication);
var
  i:integer;
begin
  inherited;
  
  ProcFalg:=True;
  while(ProcFlag)
  begin
   for i:=1 to 10 do
   begin    
    hAPP.ProcessMessages;
    Display.Text:=IntToStr(i);
    Display.Repaint;
    sleep(100);
   end;
  end;    end;    function TFilePlayer.PlayerNmae: String;
begin    end;    procedure TFilePlayer.Stop;
begin
  inherited;
  procFlag:=False;
end;    end.
jeffxx
一般會員


發表:7
回覆:22
積分:5
註冊:2003-10-10

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-08-07 14:51:12 IP:220.135.xxx.xxx 未訂閱
我找到可能的問題了 我寫dll的時候參考了 http://delphi.ktop.com.tw/topic.php?topic_id=73693 看到了Use ShareMem 我也不知道這是幹麼的反正有就抄~ 我實在想不出來程式那裡的記憶體處理那裡有可能有問題 所以就試著把ShareMem拿掉結果程式就可正常結束了程式也看不出有什麼問題 真是奇怪~ 想請教各位大大ShareMem的使用的時機是什麼時候? 還有只不過是多use了一個東西為什麼會造成程式退出錯誤 有類似單元也會造成這樣嗎? 發表人 - jeffxx 於 2005/08/07 14:58:59
pceyes
尊榮會員


發表:70
回覆:657
積分:1140
註冊:2003-03-13

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-08-07 21:45:14 IP:220.132.xxx.xxx 未訂閱
ShareMem d3前使用mapped files 要加 但之後的版本就不用了 努力會更接近成功
------
努力會更接近成功
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-08-08 01:29:12 IP:61.219.xxx.xxx 未訂閱
jeffxx
一般會員


發表:7
回覆:22
積分:5
註冊:2003-10-10

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-08-08 11:49:29 IP:61.222.xxx.xxx 未訂閱
 
感謝malanlk提供的
http://delphi.about.com/od/objectpascalide/l/aa103003a.htm
http://delphi.about.com/od/objectpascalide/l/aa103003b.htm
這兩編文章我覺得非常值得一讀
我把ShareMem放在最最前面果然可以正常結束了
之前的異常應該是我沒把ShareMem放在最最前面    簡述我看的內容:    在產生dll時delphi就會提醒你要特別處理string在library之後的註解
{ 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. }
要麻就是加上ShareMem不然就是把string改成PChar or ShortString    以下是我的疑問,因為我英文不是很好不太清楚他實際的意思    (1)文中提到delphi跟java和c#一樣object都是存在heap中那string是存在那裡的呢?    (2)string為什麼會造成問題?
   (a)定義s1:string;    => s1指向nil
   (b)初始s1:='123'     => 向記憶體要一個位置放入'123',然後把s1指到那
   (c)更動s1:=s1 '456'  => 向記憶體要一個新的位置放入'123456',s1重新指向新的位置
   以上的觀念對嗎?如果對的話傳string不就是傳一個ref而且還在同一個行程中為什麼會錯
   還是在傳的過程式他忘記自已的大小了?    (3)第二頁中他討論拿TStringList傳,如果把string包在類別裡面傳ok嗎?
   Passing objects doesn't help either這句好像是說不行的樣子    (4)拿物件來傳ok嗎?我們持有的不都是物件的ref把他從dll交到主程式上會有問題嗎
   還是他指的是不同程式語言才會有問題?
malanlk
尊榮會員


發表:20
回覆:694
積分:577
註冊:2004-04-19

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-08-08 17:28:52 IP:203.69.xxx.xxx 未訂閱
1. The task of the suballocator is to allocate all dynamic memory: from raw memory explicitly allocated by the programmer to that implicitly allocated by the compiler, as when creating strings, dynamic arrays and objects.... 2. Delphi 中 的String 不是 Null terminated(\0 結尾) "Long String" Help 中有說明 ....The eight bytes before the location contain a 32-bit length indicator and a 32-bit reference count. This memory is allocated on the heap... 表示說傳 ref 過去沒錯, 但是只有 Delphi 寫的 DLL 才看的董這樣的格式, C 就看不懂了.... 3,4. 不行 照Page2 的說法問題是卡在 heap manager 要回收 free memory 時出問題, 不是 怎樣傳遞的問題 參考這兩篇 http://delphi.ktop.com.tw/topic.php?topic_id=35228 http://delphi.ktop.com.tw/topic.php?topic_id=36703 發表人 - malanlk 於 2005/08/08 17:53:22
jeffxx
一般會員


發表:7
回覆:22
積分:5
註冊:2003-10-10

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-08-08 18:06:33 IP:61.222.xxx.xxx 未訂閱
感謝malanlk精闢的解說~
系統時間:2024-11-23 10:32:40
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!