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

使用了DLL出现access violation问题

答題得分者是:malanlk
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#1 引用回覆 回覆 發表時間:2005-08-02 15:06:43 IP:219.140.xxx.xxx 未訂閱
DLL中的函数 function showdllform(Ahandle:Thandle;Acaption:string;tablename:string):string;stdcall; var newform:Tdllsec; begin application.Handle:=Ahandle; newform:=Tdllsec.Create(application); newform.Caption:=Acaption+'(选择)'; newform.ADOTable1.TableName:=tablename; newform.ADOTable1.Active:=true; try  newform.ShowModal;  result:=resultstr; finally newform.Close; end; end;    另一个窗体: //在输入时调用dll中的表格,选择名称和号码 procedure TInput.StringGrid1DblClick(Sender: TObject); var showForm:TShowDllForm; module:Thandle;    begin  if curCol<>1 then exit;  //读入dll  module:=loadlibrary('sec.dll');  if module<32 then exit; @showForm:=getprocaddress(module,pchar(1)); if @showForm=nil then exit; //通过dll传递参数 stringgrid1.Cells[0,curRow]:=showForm(application.Handle,'选择名称','资料表'); //为代码添加名称 adoquery3.Close; adoquery3.SQL.Clear; adoquery3.SQL.Add('select 名称 from 资料表 where 代码=''' stringgrid1.Cells[0,curRow] ''''); adoquery3.Open; stringgrid1.Cells[1,curRow]:=adoquery3.fieldbyname('名称').AsString; stringgrid1.Cells[2,curRow]:='0'; stringgrid1.Cells[3,curRow]:='0'; end; 当通过DLL处理名称时 处理了几个后 出现 “Access violation at address 00402298 in module 'XXX.exe'.Write of address 01F1A888 ” 我想是不是使用了DLL的问题 有朋友说 将程序中使用完dll后 将其handle由free改为close 这样可以避免这种错误的发生 可是 我不知道 将其handle由free改为close 具体怎么写?
wameng
版主


發表:31
回覆:1336
積分:1188
註冊:2004-09-16

發送簡訊給我
#2 引用回覆 回覆 發表時間:2005-08-03 12:21:16 IP:61.222.xxx.xxx 未訂閱
必須傳遞整個 TApplication 對象,用Pointer 在Dll 的Main begin 時保留原 Dll 的Application 對象。 在 DLL_PROCESS_DETACH 還原Dll 的Application 對象。 ~~~~~~~~~~~ 難得聰明,常常糊塗。 ~~~~~~~~~~~
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#3 引用回覆 回覆 發表時間:2005-08-03 16:11:19 IP:219.140.xxx.xxx 未訂閱
......
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#4 引用回覆 回覆 發表時間:2005-08-03 16:41:17 IP:219.140.xxx.xxx 未訂閱
不好意思 感觉自己还处于初学状态 “必須傳遞整個 TApplication 對象,用Pointer 在Dll 的Main begin 時保留原 Dll 的Application 對象。 在 DLL_PROCESS_DETACH 還原Dll 的Application 對象。” 不知道 如何写... 感谢wameng
wameng
版主


發表:31
回覆:1336
積分:1188
註冊:2004-09-16

發送簡訊給我
#5 引用回覆 回覆 發表時間:2005-08-04 10:40:38 IP:61.222.xxx.xxx 未訂閱
function showdllform(MainAPP:TApplication;Acaption:string;tablename:string):string;stdcall;
var
  newform:Tdllsec;
begin
  application :=MainAPP;
  ....
end;    var
  OldDllAPP : TApplication;      procedure DllEnterPoint(Reason: Integer);
  begin
    Case Reason of
      DLL_PROCESS_ATTACH:
        begin     
          OldDllAPP := Application;             
        end;
      DLL_PROCESS_DETACH:
        begin
          Application := OldDllAPP;
        end;
    end;
  end;    exports
  ShowDllForm;    begin
  DLLProc := @DLLEnterPoint;
  DllEnterPoint(DLL_PROCESS_ATTACH);
end.
參考 ~~~~~~~~~~~ 難得聰明,常常糊塗。 ~~~~~~~~~~~
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#6 引用回覆 回覆 發表時間:2005-08-04 16:32:51 IP:219.140.xxx.xxx 未訂閱
这里全部调整后代码 如下: sec.dpr    library sec; uses   SysUtils,   Classes,   dllForm in 'dllForm.pas' {dllSec}; //此处是加入工程的unit,dllSec是该Unit的Name,而dllForm是该Unit保存的文件名 {$R *.res} exports showdllform index 1; end.    DLLForm调整为: function showdllform(MainAPP:Tapplication;Acaption:string;tablename:string):string;stdcall; var newform:Tdllsec; begin application:=MainAPP; newform:=Tdllsec.Create(application); newform.Caption:=Acaption+'(双击选择)'; newform.ADOTable1.TableName:=tablename; newform.ADOTable1.Active:=true; try  newform.ShowModal;  result:=resultstr; finally newform.Close; end; end;    var   OldDllAPP : TApplication;      procedure DllEnterPoint(Reason: Integer);   begin     Case Reason of       DLL_PROCESS_ATTACH:         begin                OldDllAPP := Application;                      end;       DLL_PROCESS_DETACH:         begin           Application := OldDllAPP;         end;     end;   end;    //-------双击选择数据栏--------- procedure TdllSec.DBGrid1DblClick(Sender: TObject); begin resultstr:=dbgrid1.Fields[0].Text; close; end;    //--------设置表宽度---------- procedure TdllSec.FormShow(Sender: TObject); var i:integer; begin for i:=0 to dbgrid1.FieldCount-1 do  dbgrid1.Columns[i].Width:=64; end;    begin   DLLProc:= @DLLEnterPoint;   DllEnterPoint(DLL_PROCESS_ATTACH);    end.    F9之  提示:Cannot debug project unless a host application is defined.Use the Run|Parameters...dialog box. 即 此时产生一个新的DLL    在DELPHI中 运行主程序 其中一个窗体(代码已在上面贴出)在输入时调用dll中的表格,选择名称和号码   提示:Project xxx.exe raised exception class EAccess Violation with message 'Access violation at address 01DC5F20 in module 'sec.dll'.Read of address 000102E6.' PROESS stopped.    推出DELPHI 直接运行该EXE程序 在输入时调用dll中的表格 选择名称和号码 时 提示:Access Violation at address 01E55F20 in module 'sec.dll'.Read of address 000602DC.    此时不能实现 在输入时调用dll中的表格 选择名称和号码    没有调整前 可以 在输入时调用dll中的表格 选择名称和号码 只是 处理了几个或十几个或几十个后 出现 “Access violation at address 00402298 in module 'XXX.exe'.Write of address 01F1A888 ” 重新运行改EXE程序 可继续(即以前出现提示问题)    我估计是我现在没有改写正确  望wameng赐教    
wameng
版主


發表:31
回覆:1336
積分:1188
註冊:2004-09-16

發送簡訊給我
#7 引用回覆 回覆 發表時間:2005-08-04 18:04:52 IP:61.222.xxx.xxx 未訂閱
我試一下,再也正常不過的事。 除了有點小問題外
  function showdllform(MainAPP:Tapplication;Acaption:string;tablename:string):String;stdcall;
  var
    newform:Tdllsec;
  begin
    Application := MainAPP;
    newform := Tdllsec.Create(application);
    newform.Caption:=Acaption '(雙擊選擇)';
    try
      newform.ShowModal;
      Result := newform.Edit1.Text;{用來測試的}
    finally
      FreeAndNil(newform);{不能用Close-> 不會釋放 NewForm}
    end;
  end;
會不會是 ADOTable 出的問題。ADOConnection 設在哪? 一般是由 主程式提供。 先把 ADOTable 遮蔽試試。 ~~~~~~~~~~~ 難得聰明,常常糊塗。 ~~~~~~~~~~~
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#8 引用回覆 回覆 發表時間:2005-08-05 13:30:09 IP:219.140.xxx.xxx 未訂閱
function showdllform(MainAPP:Tapplication;Acaption:string;tablename:string):String;stdcall; var newform:Tdllsec; begin Application := MainAPP; newform := Tdllsec.Create(application); newform.Caption:=Acaption '(双击选择)'; try newform.ShowModal; Result := newform.Edit1.Text;{用來測試的} finally FreeAndNil(newform);{不能用Close-> 不會釋放 NewForm} end; end; var OldDllAPP : TApplication; procedure DllEnterPoint(Reason: Integer); begin Case Reason of DLL_PROCESS_ATTACH: begin OldDllAPP := Application; end; DLL_PROCESS_DETACH: begin Application := OldDllAPP; end; end; end; begin DLLProc:= @DLLEnterPoint; DllEnterPoint(DLL_PROCESS_ATTACH); end. 生成DLL后 仍然提示:Project xxx.exe raised exception class EAccess Violation with message 'Access violation at address 01EE5F20 in module 'sec.dll'.Read of address 000C032E.' PROESS stopped. 只不过报错address 不同 我的ADOConnection连接的 是SQL SERVER2000中自己建立的数据库 我觉得数据库应该没有问题 如果是数据库的问题 那么我原来的情况下就应该有提示数据库连接或数据库出错的信息 ...头痛
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#9 引用回覆 回覆 發表時間:2005-08-05 13:39:12 IP:219.140.xxx.xxx 未訂閱
library sec; uses SysUtils, Classes, //此处是加入工程的unit,dllSec是该Unit的Name,而dllForm是该Unit保存的文件名 dllForm in 'dllForm.pas' {dllSec}; {$R *.res} exports //这是将要输出供外部调用的函数 showdllform index 1; begin end. function showdllform 在DLLForm里
wameng
版主


發表:31
回覆:1336
積分:1188
註冊:2004-09-16

發送簡訊給我
#10 引用回覆 回覆 發表時間:2005-08-06 13:14:40 IP:219.86.xxx.xxx 未訂閱
幾點建議:    1. 不要使用 String 因為這並非 Windows 標準,會造成不穩定!
   建議改用 PChar。
   如:
  function showdllform(MainAPP:Tapplication;Acaption:string;tablename:string):PChar;stdcall;
  var
    newform:Tdllsec;
    RltStr : String;
  begin
    Application := MainAPP;
    newform := Tdllsec.Create(application);
    newform.Caption := Acaption '(雙擊選擇)';
    try
      newform.ShowModal;
      RltStr := newform.Edit1.Text;
      GetMem(Result,Length(RltStr));
      Result := PChar(RltStr);
    finally
      FreeAndNil(newform);{不能用Close-> 不會釋放 NewForm}
    end;
  end;    2. 不要用字串當作回傳值,容易造成混淆。
   誰去建立與釋放?    3. 最後提醒您! 
   DLLProc:= @DLLEnterPoint;
   DllEnterPoint(DLL_PROCESS_ATTACH);
   是放在 library sec 的 Begin ..End 中。    Good Luck ...
~~~~~~~~~~~ 難得聰明,常常糊塗。 ~~~~~~~~~~~ 發表人 - wameng 於 2005/08/06 13:15:05
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#11 引用回覆 回覆 發表時間:2005-08-07 22:33:32 IP:219.140.xxx.xxx 未訂閱
现在调整为 library sec; uses SysUtils, Classes, //此处是加入工程的unit,dllSec是该Unit的Name,而dllForm是该Unit保存的文件名 dllForm in 'dllForm.pas' {dllSec}; {$R *.res} exports //这是将要输出供外部调用的函数 showdllform index 1; begin DLLProc:= @DLLEnterPoint; DllEnterPoint(DLL_PROCESS_ATTACH); end. ------------------------------------------- unit dllForm; {$R *.dfm} function showdllform(MainAPP:Tapplication;Acaption:string;tablename:string):PChar;stdcall; var newform:Tdllsec; RltStr : String; begin Application := MainAPP; newform := Tdllsec.Create(application); newform.Caption := Acaption '(雙擊選擇)'; try newform.ShowModal; RltStr := newform.Edit1.Text; GetMem(Result,Length(RltStr)); Result := PChar(RltStr); finally FreeAndNil(newform);{不能用Close-> 不會釋放 NewForm} end; end; var OldDllAPP : TApplication; procedure DllEnterPoint(Reason: Integer); begin Case Reason of DLL_PROCESS_ATTACH: begin OldDllAPP := Application; end; DLL_PROCESS_DETACH: begin Application := OldDllAPP; end; end; end; end. --------------- F9之 提示: Symbol'INDEX' is specific to a platform 同时 DLLProc:= @DLLEnterPoint; 高亮显示 在此 多谢wameng悉心回复 我原来的目的只是希望实现双击窗体上stringgrid1.Cells可出现资料表数据 然后 双击资料表数据 将对应的资料表中的名称 返回到stringgrid1.Cells上 没想到搞的这么麻烦 不好意思啊 有个朋友说 就把 “DLL中的函数 function showdllform(Ahandle:Thandle;Acaption:string;tablename:string):string;stdcall; var newform:Tdllsec; begin application.Handle:=Ahandle; newform:=Tdllsec.Create(application); newform.Caption:=Acaption '(选择)'; newform.ADOTable1.TableName:=tablename; newform.ADOTable1.Active:=true; try newform.ShowModal; result:=resultstr; finally newform.Close; end; end;” 中的 newform.Close; 改为 newform.free;. 我马上会数据测试看看
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#12 引用回覆 回覆 發表時間:2005-08-08 18:42:08 IP:219.140.xxx.xxx 未訂閱
newform.Close; 改为 newform.free;. 不行 将close 改为free后 可生成一个新的DLL 但处理一个后 程序则死机 必须重新启动程序 然后在处理一个 又死机 ......
malanlk
尊榮會員


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

發送簡訊給我
#13 引用回覆 回覆 發表時間:2005-08-08 19:38:46 IP:203.69.xxx.xxx 未訂閱
這個問題應該是和回答 jeffxx 的問題相同 http://delphi.ktop.com.tw/topic.php?TOPIC_ID=76298
wameng
版主


發表:31
回覆:1336
積分:1188
註冊:2004-09-16

發送簡訊給我
#14 引用回覆 回覆 發表時間:2005-08-08 23:49:00 IP:219.86.xxx.xxx 未訂閱
老實說,我覺得您的問題不在DLL form 在於 傳遞資料及指針上的問題。 建議改為 function showdllform(MainAPP:Tapplication;Acaption:string;tablename:string):PChar; begin .... Result := StrNew(PChar('要回傳內容.....')); 要不然將程序上傳。 或者 Email 至 cool.evon@msa.hinet.net。 我幫你看一看。因該問題不大! 唉!最近有點頭暈及有越來越迷糊的趨勢。 該不會是老了。.... ~~~~~~~~~~~ 難得聰明,常常糊塗。 ~~~~~~~~~~~
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#15 引用回覆 回覆 發表時間:2005-08-09 04:01:15 IP:219.140.xxx.xxx 未訂閱
(我下面的描述可能会长一点)    这里 我总结一下代码和测试情况 首先 强调一下这些代码的目的: 是希望实现双击窗体上stringgrid1.Cells可出现资料表数据窗体 然后 双击资料表数据 将对应的资料表中的名称  返回到stringgrid1.Cells上    原来的所有源代码如下:    ------------------- library sec; uses   SysUtils,   Classes,   dllForm in 'dllForm.pas' {dllSec}; {$R *.res} exports showdllform index 1; begin end. -------------------- unit dllForm; interface uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,   Dialogs, DB, Grids, DBGrids, ADODB; type   TdllSec = class(TForm)     ADOTable1: TADOTable;     DBGrid1: TDBGrid;     DataSource1: TDataSource;     procedure DBGrid1DblClick(Sender: TObject);     procedure FormShow(Sender: TObject);   private     { Private declarations }   public     { Public declarations }   end; function showdllform(Ahandle:Thandle;Acaption:string;tablename:string):string;stdcall; var  resultstr:string; implementation    {$R *.dfm}    function showdllform(Ahandle:Thandle;Acaption:string;tablename:string):string;stdcall; var newform:Tdllsec; begin application.Handle:=Ahandle; newform:=Tdllsec.Create(application); newform.Caption:=Acaption+'(双击选择)'; newform.ADOTable1.TableName:=tablename; newform.ADOTable1.Active:=true; try  newform.ShowModal;  result:=resultstr; finally newform.Close; end; end; //-------双击选择数据栏--------- procedure TdllSec.DBGrid1DblClick(Sender: TObject); begin resultstr:=dbgrid1.Fields[0].Text; close; end; //--------设置表宽度---------- procedure TdllSec.FormShow(Sender: TObject); var i:integer; begin for i:=0 to dbgrid1.FieldCount-1 do  dbgrid1.Columns[i].Width:=64; end;    end. ---------------------以上生成DLL    -------------------------- 主程式下调用DLL的窗体设置的相应代码    unit unit1;    interface    uses   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,   Dialogs, ComCtrls, ToolWin, ImgList, Grids, DBGrids, ExtCtrls, StdCtrls,   Buttons, DB, ADODB, DBCtrls, Mask; ...... procedure TInput.StringGrid1DblClick(Sender: TObject); var showForm:TShowDllForm; module:Thandle;    begin if curCol<>1 then exit; //读入dll module:=loadlibrary('sec.dll'); if module<32 then exit; @showForm:=getprocaddress(module,pchar(1)); if @showForm=nil then exit; //通过dll传递参数 stringgrid1.Cells[0,curRow]:=showForm(application.Handle,'选择名称','资料表'); //为代码添加名称 adoquery3.Close; adoquery3.SQL.Clear; adoquery3.SQL.Add('select 名称 from 资料表 where 代码=''' stringgrid1.Cells[0,curRow] ''''); adoquery3.Open; stringgrid1.Cells[1,curRow]:=adoquery3.fieldbyname('名称').AsString; stringgrid1.Cells[2,curRow]:='0'; stringgrid1.Cells[3,curRow]:='0'; end; ...... -------------------------- 此阶段出现问题:当通过DLL处理名称时 处理了几个后 出现 “Access violation at address 00402298 in module 'XXX.exe'.Write of address 01F1A888 ” 关闭应用程序 再进入 可继续通过DLL处理名称 只是 又处理了几个后 仍出现如上错误提示信息 然后又得关闭应用程序 再进入 个人感觉可能是释放问题 TO: malanlk 你好 谢谢你的回帖 这个帖子后面有很多好的关于DLL方面应用的例子 很多都和我这个情况类似(可以说 在测试的这段过程中 他们出现的问题 我都出现过 而且错误提示信息基本相同) 刚才我花一点时间专门对这段代码(双击窗体上stringgrid1.Cells可出现资料 表数据 然后 双击资料表数据 将对应的资料表中的名称 返回到stringgrid1.Cells上)进行了测试 概括分为以下几种情况: 情况一:参照 http://delphi.ktop.com.tw/topic.php?TOPIC_ID=76298 中jeffxx 的类似解决方法: 在unit dllForm加入ShareMem 且把ShareMem放在最最前面 ------------------- library sec; uses SysUtils, Classes, dllForm in 'dllForm.pas' {dllSec}; {$R *.res} exports showdllform index 1; begin end. -------------------- unit dllForm; interface uses sharemem,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, DB, Grids, DBGrids, ADODB; type TdllSec = class(TForm) ADOTable1: TADOTable; DBGrid1: TDBGrid; DataSource1: TDataSource; procedure DBGrid1DblClick(Sender: TObject); procedure FormShow(Sender: TObject); private { Private declarations } public { Public declarations } end; function showdllform(Ahandle:Thandle;Acaption:string;tablename:string):string;stdcall; var resultstr:string; implementation {$R *.dfm} function showdllform(Ahandle:Thandle;Acaption:string;tablename:string):string;stdcall; var newform:Tdllsec; begin application.Handle:=Ahandle; newform:=Tdllsec.Create(application); newform.Caption:=Acaption '(双击选择)'; newform.ADOTable1.TableName:=tablename; newform.ADOTable1.Active:=true; try newform.ShowModal; result:=resultstr; finally newform.Close; end; end; //-------双击选择数据栏--------- procedure TdllSec.DBGrid1DblClick(Sender: TObject); begin resultstr:=dbgrid1.Fields[0].Text; close; end; //--------设置表宽度---------- procedure TdllSec.FormShow(Sender: TObject); var i:integer; begin for i:=0 to dbgrid1.FieldCount-1 do dbgrid1.Columns[i].Width:=64; end; end. --------------------- F9之 提示产生新的DLL 再对主程式F9(此时主程式下的uses下 未加 sharemem) 调用dll中的表格,选择名称和号码 程序退出时 提示invalid pointer operation 錯誤訊息 有点类似http://delphi.ktop.com.tw/topic.php?TOPIC_ID=26599中degr 的一种情况下的错误 情况二:参考 jeffxx 他原来所借鉴的 http://delphi.ktop.com.tw/topic.php?topic_id=73693 中 reptile 的解答 “librarys.dpr 要加 uses sharememrep; moneyshop.dpr(主程式) 也要加 uses sharememrep; 有用到 dll 的地方最好也加上 uses sharememrep;” 在uses最前面加上sharememrep 但我这里提示:File not Found :'sharememrep.dcu' 我又参考http://delphi.ktop.com.tw/topic.php?topic_id=73693 中 jumo的解答 “請檢查以下幾點 1. Libary 有無 Use ShareMem, 而且要放在第一個 2. 主程式 有無 Use ShareMem, 而且要放在第一個 3. reptile 所指點用的 ShareMemRep 這個 unit 我沒用過, 改試試看 ShareMem.” 于是 我把sharememrep改为sharemem加上去 我原来的代码就调整为(以下只写和原代码不同的部分 基本上是uses部分): -------------------------- library sec; uses sharemem, SysUtils, Classes, dllForm in 'dllForm.pas' {dllSec}; ... --------------------------//library sec所对应的unit dllForm的uses下未加sharemem -------------------------- 主程式下调用DLL的窗体设置的相应代码 unit unit1; interface uses sharemem,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, ToolWin, ImgList, Grids, DBGrids, ExtCtrls, StdCtrls, Buttons, DB, ADODB, DBCtrls, Mask; ...... -------------------------- 程序在退出时 提示:invalid pointer operation 錯誤訊息 若是 在library sec ;其对应的unit dllForm;主程式下调用DLL unit unit1;的uses部分 都 在最前面加上sharemem 则 运行程序时 即 提示 invalid pointer operation 錯誤訊息 若是 只在library sec所对应的unit dllForm的uses下 加sharemem 即library sec;主程式下调用DLL unit unit1;都不加sharemem 则在程序调用DLL后 程序在退出时 提示 invalid pointer operation 錯誤訊息 若是 只在library sec下的uses 部分最前面加sharemem 即library sec所对应的unit dllForm的uses下; 主程式下调用DLL unit unit1; 都不加sharemem 则程序运行 调用DLL 退出 都无提示错误信息 只是在通过DLL处理名称时 处理了几个后 又出现 “Access violation at address 00402298 in module 'XXX.exe'.Write of address 01F1A888 ”即我现在代码中遇到的 问题 情况三: http://delphi.ktop.com.tw/topic.php?TOPIC_ID=55744 中juneo 的"Invalid pointer operation"解决方式是 “作下列的修正,就可以傳回正確答案。 Result := PChar(IntToHex(J,2));”----------他的Result和我的Result效果作用我觉得一样 这是不是wameng刚才说的 “老實說,我覺得您的問題不在DLL form 在於 傳遞資料及指針上的問題。 建議改為 function showdllform(MainAPP:Tapplication;Acaption:string;tablename:string):PChar; begin .... Result := StrNew(PChar('要回傳內容.....'));”? 其实 我还是希望把unit dllForm中的 “newform.ADOTable1.TableName:=tablename; newform.ADOTable1.Active:=true;”加进去修改 毕竟是希望通过双击数据库表中字段返回到主程式的tringgrid1.Cells上 谢谢 wameng malanlk 有你们真好
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#16 引用回覆 回覆 發表時間:2005-08-09 04:07:05 IP:219.140.xxx.xxx 未訂閱
wameng malanlk 辛苦两位了
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#17 引用回覆 回覆 發表時間:2005-08-09 04:08:31 IP:219.140.xxx.xxx 未訂閱
头昏中......
malanlk
尊榮會員


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

發送簡訊給我
#18 引用回覆 回覆 發表時間:2005-08-09 08:20:54 IP:203.69.xxx.xxx 未訂閱
1. 建議用 http://delphi.ktop.com.tw/topic.php?topic_id=35228 的 sharememrep.pas 效能比較好 2. 建議您回應的程式碼用 [code]...〈程式碼〉...[/code]夾起來, 縮排就不會跑掉了. 3. ShareMemRep(ShareMem) 通常加一次就夠了加在.dpr的檔案內就可以了. 簡單的說明一下: 引發 "invalid pointer operation" 的原因是 DLL 和 EXE 使用了相同但各自獨立的記憶體管理機制, 所以在記憶體做回收合併時無法判斷記憶體區塊已經被釋放(由DLL建立,EXE釋放)而又做一次釋放的動作,所造成的. ShareMemRep 的作用就是希望EXE,DLL 用同一個記憶體管理機制. 之所以要加在最前面, 是因為 Compiler 會依照 uses 中列出的順序載入 Unit, 並執行 Initialization 及 Finalization 中的程式碼, 所以替換記憶體管理機制最好的時機就是加在 uses 最前面. .dpr 又是第一個被載入所以應該加在.dpr. 4. 經由上述說明 你第1個 invalid pointer... 是dll用了 ShareMem 機制, exe 還是用原來機制, 等於沒改. 第2,3個invalid pointer.. 是因為 ShareMem 沒加在主程式的 .dpr 檔案內, .dpr 檔案內的 uses 還是用原來的機制. 你在情況二最後又把 sec.dpr uses 中的 ShareMem 拿掉 當然就恢復原狀況了... 6. 結論是: 請在 主程式(xxx.dpr)及DLL(sec.dpr) 的 .dpr 檔案中的 uses 中加入 ShareMem 而且要在第一個....在提醒一次兩個都要加哦! 先這樣試試吧....
jeffxx
一般會員


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

發送簡訊給我
#19 引用回覆 回覆 發表時間:2005-08-09 08:58:28 IP:61.222.xxx.xxx 未訂閱
function showdllform(MainAPP:Tapplication;Acaption:string;tablename:string):PChar; 說明上是說 if your DLL exports any procedures or functions that pass strings as parameters or function results 你要不要把引數(action、tablename)改成pchar試試 不然就先把string拿掉,值寫在dll中,把回傳值寫interger或其它的 先測功能有沒有 如果你要加sharemem 請加在最最前面 主程式加在 program Project1; <===加在這裡,不要加在其它unit裡面 uses ShareMem, Forms, dll內容 library Project1; <====加在這裡,不要加在其它unit裡面 uses ShareMem, SysUtils, Classes, Unit2 in 'Unit2.pas'; 以上是之前的測試 sorry 沒看清楚以上內就是malanlk大大上面的回覆 發表人 - jeffxx 於 2005/08/09 09:25:38 發表人 - jeffxx 於 2005/08/09 09:39:33 發表人 - jeffxx 於 2005/08/09 10:23:55
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#20 引用回覆 回覆 發表時間:2005-08-09 15:21:30 IP:219.140.xxx.xxx 未訂閱
SORRY 昨天写的时候 把主程式下调用DLL的窗体 和 主程式搞混淆了
 
library sec;
uses
  sharemem,
  SysUtils,
  Classes,
  dllForm in 'dllForm.pas' {dllSec};
......
主程式
 
unit MainForm;    interface    uses
  sharemem,Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, Menus, ComCtrls, DB, ADODB, StdCtrls;
......
程序在退出时 还是提示:invalid pointer operation 錯誤訊息
malanlk
尊榮會員


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

發送簡訊給我
#21 引用回覆 回覆 發表時間:2005-08-09 15:38:39 IP:203.69.xxx.xxx 未訂閱
我說的是主程式的 xxx.dpr project 檔哦, 不是 .pas 檔. 功能表中 Project--> View Source 就可以看到 .dpr 的檔案了... 開頭應該是
program xxx;    uses 
  ShareMem, // 加在這裡
  Forms,
   ....
   ....
發表人 - malanlk 於 2005/08/09 15:45:35
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#22 引用回覆 回覆 發表時間:2005-08-09 17:20:14 IP:219.140.xxx.xxx 未訂閱
真心感谢各位大大的 悉心指导  在下感激不尽 尤其是感谢 malanlk   wameng  jeffxx    TO  wameng: 阁下根本没老 你的回帖让我了解和学到了很多这方面的知识 积累了这方面的经验 再次谢谢你 LUCKY YOU  LUCKY ME LUCKY US!        后注: 考虑到malanlk的建议 “1. 建議用http://delphi.ktop.com.tw/topic.php?topic_id=35228 的sharememrep.pas 效能比較好” 我在http://delphi.ktop.com.tw/topic.php?topic_id=35228下sharememrep 1.3和 sharememrep1.52    ShareMemRep解压到目标文件夹(主程式和DLL文件夹) 则此时在uses中可以  加入ShareMemRep而不会提示 file nor found'ShareMemRep.dcu'    当 program Project1; uses ShareMemrep, Forms,    dll內容    library Project1;  uses ShareMemrep, SysUtils, Classes, Unit2 in 'Unit2.pas';    执行程序 调用DLL中 名称 时    sharememrep1.3下  提示:GOD,is a frightful calamity,Some library none load...You must Freelibrary()  for all dynamic library before process terminate!    sharememrep1.52下 提示: MemMgr Invalid! -Have Loadlibrary(),but none Free library()! -Have some memory leak!    于是我在    主程式下调用DLL的窗体设置的相应代码
 
unit unit1;    interface    uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, ToolWin, ImgList, Grids, DBGrids, ExtCtrls, StdCtrls,
  Buttons, DB, ADODB, DBCtrls, Mask;
......
procedure TInput.StringGrid1DblClick(Sender: TObject);
var
showForm:TShowDllForm;
module:Thandle;    begin
if curCol<>1 then exit;
module:=loadlibrary('sec.dll');
if module<32 then exit;
@showForm:=getprocaddress(module,pchar(1));
if @showForm=nil then exit;
stringgrid1.Cells[0,curRow]:=showForm(application.Handle,'选择名称','资料表');        freelibrary(module);// 加入freelibrary    adoquery3.Close;
adoquery3.SQL.Clear;
adoquery3.SQL.Add('select 名称 from 资料表 where 代码=''' stringgrid1.Cells[0,curRow] '''');
adoquery3.Open;
stringgrid1.Cells[1,curRow]:=adoquery3.fieldbyname('名称').AsString;
stringgrid1.Cells[2,curRow]:='0';
stringgrid1.Cells[3,curRow]:='0';    end;    ......
执行程序 在通过DLL处理名称时 提示我在调用DLL的窗体中 另一过程的一个变量设置有问题 http://delphi.ktop.com.tw/topic.php?topic_id=35228中 Aimingoo 提到“使用ShareMemRep,可以徹底地拋開BORLNDMM.DLL和ShareMem.pas單元。 你無需再關心ShareMem的細節,因為DLL與EXE使用了同一個內存管理器。由此帶來的另一個好處是: 你可以隨意替換EXE中的內存管理器,而無需更改DLL中的任何代碼” 以后程序发布 是不是要把BORLNDMM.DLL一起发布?那样岂不是有些麻烦
malanlk
尊榮會員


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

發送簡訊給我
#23 引用回覆 回覆 發表時間:2005-08-09 18:14:54 IP:203.69.xxx.xxx 未訂閱
1."徹底地拋開BORLNDMM.DLL...." 就是不用再發佈...    2. http://delphi.about.com/od/objectpascalide/l/aa103003b.htm 中的 FastSharemem unit http://delphi.about.com/gi/dynamic/offsite.htm?site=http://www.codexterity.com/fastsharemem.htm 也可以試試...速度據說都有 4-8 倍以上
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#24 引用回覆 回覆 發表時間:2005-08-09 18:30:40 IP:219.140.xxx.xxx 未訂閱
"徹底地拋開BORLNDMM.DLL...." 就是不用再發佈... 我明白使用sharememrep后BORLNDMM.DLL就不必再发布 我想问的是 如果就是sharemem 那么以后再发布程序时是不是需要做些对于BORLNDMM.DLL的处理?
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

發送簡訊給我
#25 引用回覆 回覆 發表時間:2005-08-09 18:35:26 IP:219.140.xxx.xxx 未訂閱
使用fastsharemem在窗体调用DLL返回时 没问题 但程序退出后 就提示Access Violation 错误 在USES最前面加sharemem 则没有问题
malanlk
尊榮會員


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

發送簡訊給我
#26 引用回覆 回覆 發表時間:2005-08-09 19:12:38 IP:203.69.xxx.xxx 未訂閱
ShareMemRep, FastShareMem 我都沒用過, 你可以直接發信跟 Aimingoo 指教 如果是用 ShareMem 就將 BORLNDMM.DLL 跟主程式放在一起就可以了, 或是放在 SYSTEM32 下也可以..這樣應該就可以了
baby2321
初階會員


發表:52
回覆:165
積分:48
註冊:2005-06-11

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