有这样一个现象:
当exe和dll引用同一个forms.pas文件以后,那么请看下面代码:library mydll
interface
uses
windows,sysutils,forms;procedure test;external;stdcall;
implementation
{$R *.res}
procedure test;external;stdcall;
begin
showmessage(application.title);
end;
end.///////////////////////////////////program myexeuses
windows,sysutils,forms;
{$R *.res}
var
hlib:dword;
p:tprocedure;
begin
application.initialize;
application.title:='ok!'
hlib:=loadlibrary("mydll.dll");
p:=getprocaddress(hlib,"test");
if assigned(p) then p();//竟然能够显示'ok!'
freelibrary(hlib);
application.run;
end.//////////////////////////我们知道,application是forms.pas单元中的全局变量。
dll里面并没有对application做初始化,但是调用test的时候,dll里访问了在exe中做好了初始化的application变量。问题:是不是因为同一个进程中exe和dll共享一切内存,完全透明,并且只要引用了同一个单元,那么在任何编译好的pe文件中,该单元的资源,比如全局变量、常量、函数等,都被固化到了相同的rva地址?
当exe和dll引用同一个forms.pas文件以后,那么请看下面代码:library mydll
interface
uses
windows,sysutils,forms;procedure test;external;stdcall;
implementation
{$R *.res}
procedure test;external;stdcall;
begin
showmessage(application.title);
end;
end.///////////////////////////////////program myexeuses
windows,sysutils,forms;
{$R *.res}
var
hlib:dword;
p:tprocedure;
begin
application.initialize;
application.title:='ok!'
hlib:=loadlibrary("mydll.dll");
p:=getprocaddress(hlib,"test");
if assigned(p) then p();//竟然能够显示'ok!'
freelibrary(hlib);
application.run;
end.//////////////////////////我们知道,application是forms.pas单元中的全局变量。
dll里面并没有对application做初始化,但是调用test的时候,dll里访问了在exe中做好了初始化的application变量。问题:是不是因为同一个进程中exe和dll共享一切内存,完全透明,并且只要引用了同一个单元,那么在任何编译好的pe文件中,该单元的资源,比如全局变量、常量、函数等,都被固化到了相同的rva地址?
dll中的application对象与调用它的程序是分离的,
应该是没有什么关系
但是为什么显示ok,不知道了~
等高人吧~
application.initialize;
application.title := 'abc';
hlib:=loadlibrary("mydll.dll"); //now the library cache the application module
//name to it's title property, the value is
//abc
application.title :='ok!' //now we change to 'ok', but the dll application
//property Title will not changed p:=getprocaddress(hlib,"test");
if assigned(p) then
begin
p(); //here, it will be show 'abc' rather 'ok'
end;
freelibrary(hlib);
application.run;
你可以参考TApplication.Create()的代码,它里面有对Title属性的初始化
对于一个DLL或Package,它的Title被初始化为宿主应用程序(exe)的Module Name,
也就是title,但是一旦这个DLL的Application对象的Title被初始化后,不管exe方面怎样变化它就不再变化了,所以我说它把module name cache起来了,关于这一点,
详见TApplication.GetTitle()的代码以上就是你给出的例子以及我改后的例子之所以得出那样的结果的原因
至于你说的是不是因为同一个进程中exe和dll共享一切内存,完全透明,
并且只要引用了同一个单元,那么在任何编译好的pe文件中,该单元的资源,
比如全局变量、常量、函数等,都被固化到了相同的rva地址?”则是错误的,dll中的所有单元和exe中的所有单元都是分离的,各自都有一个副本
的
的,除非它们都build with runtime library,那么这些被build with
的runtime library中的单元的数据则是共享的
-------------------
function TApplication.GetTitle: string;
var
Buffer: array[0..255] of Char;
begin
if FHandleCreated then
SetString(Result, Buffer, GetWindowText(FHandle, Buffer,
SizeOf(Buffer))) else
Result := FTitle;
end;procedure TApplication.SetTitle(const Value: string);
begin
if FHandleCreated then
begin
if (GetTitle <> Value) or (FTitle <> '') then
begin
SetWindowText(FHandle, PChar(Value));
FTitle := '';
end;
end
else
FTitle := Value;
end;这里只是设定ftitle,设置ftitle而已啊,当然同时设定了windowtest。