关于DLL的两个问题,请各位帮忙解决,在线等待。 ( 积分: 80 )

  • 主题发起人 主题发起人 twquac
  • 开始时间 开始时间
T

twquac

Unregistered / Unconfirmed
GUEST, unregistred user!
问题一:
A为EXE,B为DLL,C为DLL
主程序(A)调用动态库B,B上有一事件可调用C,如果不进行参数传递到C,则C能否得知B所在文件路径?

问题二:
看下面代码:

library MachineInterface;

{ 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
SysUtils,
Windows,
System,
Forms,
dialogs,
Classes;
type
SetRegModeDll=function (MachineAddr:integer;RegMode:integer):integer;stdcall;
ClearAlarmClockDll=function (MachineAddr:integer):integer;stdcall;

Const
InterfaceFile=‘Test.dll';

var
DllHandle:THandle;
Dllfarproc:Tfarproc;

function SetRegMode(MachineAddr,ComPort,Baud,RegMode:integer):boolean;stdcall;
begin
Result:=False;
if DllHandle>32 then
if OpenComPort(ComPort,Baud) then
begin
DllfarProc:=GetProcAddress(DllHandle,'SetMode'); //获取函数入口
if DllfarProc<>Nil then
Result:=(SetRegModeDll(DllfarProc)(MachineAddr,RegMode)=0);
CloseComPort;
end;
end;

function ClearAlarmClock(MachineAddr,ComPort,Baud:integer):Boolean;stdcall;
begin
Result:=False;
if DllHandle>32 then
if OpenComPort(ComPort,Baud) then
begin
DllfarProc:=GetProcAddress(DllHandle,'ClearSirenTable'); //获取函数入口
if DllfarProc<>Nil then
Result:=(ClearAlarmClockDll(DllfarProc)(MachineAddr)=0);
CloseComPort;
end;
end;

{$R *.res}

exports
SetReadMode,ClearAlarmClock;

procedure DLLUnloadProc(Reason: Integer); register;
begin
{DLL_PROCESS_ATTACH:进程进入时
 DLL_PROCESS_DETACH进程退出时
 DLL_THREAD_ATTACH 线程进入时
 DLL_THREAD_DETACH 线程退出时}
[red]if Reason = DLL_PROCESS_DETACH then
FreeLibrary(DllHandle);[/red]end; //为什么带了条件(if Reason = DLL_PROCESS_DETACH then),一调用DLL还是会执行FreeLibary(DllHandle),
begin
DllHandle:=LoadLibrary(InterfaceFile);
DLLProc := @DLLUnloadProc;
DLLUnloadProc(DLL_PROCESS_DETACH);
end.
我只想在退出调用DLL后再FreeLibary(InterfaceFile),到底该如何写代码?
 
问题一:
A为EXE,B为DLL,C为DLL
主程序(A)调用动态库B,B上有一事件可调用C,如果不进行参数传递到C,则C能否得知B所在文件路径?

问题二:
看下面代码:

library MachineInterface;

{ 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
SysUtils,
Windows,
System,
Forms,
dialogs,
Classes;
type
SetRegModeDll=function (MachineAddr:integer;RegMode:integer):integer;stdcall;
ClearAlarmClockDll=function (MachineAddr:integer):integer;stdcall;

Const
InterfaceFile=‘Test.dll';

var
DllHandle:THandle;
Dllfarproc:Tfarproc;

function SetRegMode(MachineAddr,ComPort,Baud,RegMode:integer):boolean;stdcall;
begin
Result:=False;
if DllHandle>32 then
if OpenComPort(ComPort,Baud) then
begin
DllfarProc:=GetProcAddress(DllHandle,'SetMode'); //获取函数入口
if DllfarProc<>Nil then
Result:=(SetRegModeDll(DllfarProc)(MachineAddr,RegMode)=0);
CloseComPort;
end;
end;

function ClearAlarmClock(MachineAddr,ComPort,Baud:integer):Boolean;stdcall;
begin
Result:=False;
if DllHandle>32 then
if OpenComPort(ComPort,Baud) then
begin
DllfarProc:=GetProcAddress(DllHandle,'ClearSirenTable'); //获取函数入口
if DllfarProc<>Nil then
Result:=(ClearAlarmClockDll(DllfarProc)(MachineAddr)=0);
CloseComPort;
end;
end;

{$R *.res}

exports
SetReadMode,ClearAlarmClock;

procedure DLLUnloadProc(Reason: Integer); register;
begin
{DLL_PROCESS_ATTACH:进程进入时
 DLL_PROCESS_DETACH进程退出时
 DLL_THREAD_ATTACH 线程进入时
 DLL_THREAD_DETACH 线程退出时}
[red]if Reason = DLL_PROCESS_DETACH then
FreeLibrary(DllHandle);[/red]end; //为什么带了条件(if Reason = DLL_PROCESS_DETACH then),一调用DLL还是会执行FreeLibary(DllHandle),
begin
DllHandle:=LoadLibrary(InterfaceFile);
DLLProc := @DLLUnloadProc;
DLLUnloadProc(DLL_PROCESS_DETACH);
end.
我只想在退出调用DLL后再FreeLibary(InterfaceFile),到底该如何写代码?
 
begin
DllHandle:=LoadLibrary(InterfaceFile);
DLLProc := @DLLUnloadProc;
DLLUnloadProc(DLL_PROCESS_DETACH);
end.

这个地方

DLLUnloadProc(DLL_PROCESS_DETACH);
->>>
DLLUnloadProc(DLL_PROCESS_ATTACH);
 
问题1, 至少要传递一个DLL 句柄,或者DLL的文件名

问题2, 你的DLL 主过程中的最后一行代码写错了,可能是笔误吧
 
可是,我想在退出时执行FreeLibrary(DllHandle)操作呀!
 
to tseug
按你的方法
DLLUnloadProc(DLL_PROCESS_DETACH);
->>>
DLLUnloadProc(DLL_PROCESS_ATTACH);
这样修改过,在DLL退出时会执行 FreeLibrary(DllHandle)这段代码吗
to lich
对于问题一,假如我知道调用该DLL的DLL的文件名,又如何得知其位置呢?
 
经我按下面代码测试
procedure DLLUnloadProc(Reason: Integer);far; stdcall;
begin
{DLL_PROCESS_ATTACH:进程进入时
 DLL_PROCESS_DETACH进程退出时
 DLL_THREAD_ATTACH 线程进入时
 DLL_THREAD_DETACH 线程退出时}
if Reason = DLL_PROCESS_DETACH then
begin
FreeLibrary(DllHandle);
showmessage('ok');
end;
end;
begin
DllHandle:=LoadLibrary(InterfaceFile);
DLLProc := @DLLUnloadProc; //DllProc为DLL的初始化和退出清理
DLLUnloadProc(DLL_PROCESS_ATTACH);
end.
发现,在退出DLL时根本就不会执行
if Reason = DLL_PROCESS_DETACH then
begin
FreeLibrary(DllHandle);
showmessage('ok');
end;
 
会的,你可以Delphi的调试器设断点来看看
 
to tseug
我用showmessage('ok')测试过,退出时根本没执行
 
各位怎么都不说话了呢?
 
对于问题一,假如我知道调用该DLL的DLL的文件名,又如何得知其位置呢?
可以这样得到:(c代码)
char buf[256];//返回dll文件路径
HMODULE hmod = GetModuleHandle(&quot;kernel32.dll&quot;);
GetModuleFileName(hmod,buf,255);
cout << buf << endl;
 
没错,如 wqyzsh 所说
 
to wqyzsh,lich
转为delphi代码呢?
 
设断点调试啊,肯定执行的时候有问题
 
一个小例子,你看看吧

library MiniDll;

const
DLL_PROCESS_DETACH = 0;
DLL_PROCESS_ATTACH = 1;
DLL_THREAD_ATTACH = 2;
DLL_THREAD_DETACH = 3;

function MessageBox(hWnd: LongWord; lpText, lpCaption: PChar; uType: LongWord): Integer; stdcall;
external 'user32.dll' name 'MessageBoxA';

const
MB_ICONINFORMATION = $00000040;

var
sArr : array [0..3] of pChar
= ('PROCESS_DETACH',
'PROCESS_ATTACH',
'THREAD_ATTACH',
'THREAD_DETACH');

procedure Same_DllMain(Reason: Integer);
begin
case Reason of
DLL_PROCESS_ATTACH,
DLL_THREAD_ATTACH,
DLL_THREAD_DETACH,
DLL_PROCESS_DETACH :
MessageBox(0, sArr[Reason], 'MiniDll', MB_ICONINFORMATION);
end;
end;

begin
DllProc := @Same_DllMain;
Same_DllMain(DLL_PROCESS_ATTACH);
end.
 
楼主声明的时候,为什么要在过程的最后加上 far; stdcall; 呢

procedure DLLUnloadProc(Reason: Integer);far; stdcall;

是谁告诉你这么做的,去掉就行了
 
to lich
为什么我在网上看到很多都有类似DLLUnloadProc(Reason: Integer); register;之类的?
 
是啊,我也奇怪为什么你会这么写?

你能告诉我原因吗?

你在Delphi的帮助中,直接输入: DLLProc

我不否认,很多人有足够的创造力,但是创造力应该用在正确的地方吧

还有: 当遇到问题时,你第一个想到的应该是Delphi自己的帮助
干吗要舍近求远呢,是不是啊?
 
后退
顶部