ang*_*son 1 .net delphi dll host runtime
我们有自己的glue-layer-code-thingamajig,它允许我们在Win32 Delphi程序中托管.NET运行时.这使我们可以逐步过渡到.NET.
但是,我们不时会遇到一些问题,昨天我在SO上看到了一个答案,提到了Jcl的.NET主机实现,所以我想我会看看是否存在一些明显的差异.
原来有,但我不明白它做了什么,为什么,以及我是否需要做同样的事情.我当然会尝试一下,但我非常希望有人能够理解这个奇怪代码背后的原因告诉我它的作用.
随着时间的推移,我们可能会转而使用Jcl实现,但由于我们有即将发布的版本,除非为了解决当前的问题是绝对必要的,否则在此级别的代码进行重大改革是不合理的,所以请不要我只是建议我们切换.
无论如何,差异在于它们如何调用.NET函数来加载和绑定到.NET运行时,基本上它们是如何从.NET dll调用导出的函数的.
这是我的代码:
type
TCorBindToRuntimeEx = function(pwszVersion: PWideChar;
pwszBuildFlavor: PWideChar;
startupFlags: DWord; rclsid, riid: PGUID;
out ppv: IUnknown): Integer; stdcall;
...
var
CorBindToRuntimeEx : TCorBindtoRuntimeEx = nil;
...
CorBindToRuntimeEx := GetProcAddress(Runtimehandle, 'CorBindToRuntimeEx');
...
clsid := CLASS_CorRuntimeHost;
iid := IID_ICorRuntimeHost;
rc := CorBindToRuntimeEx('v2.0.50727', 'wks', 0, @clsid,
@iid, UnkRuntimeEngine);
Run Code Online (Sandbox Code Playgroud)
现在,我在这里简单地使用GetProcAddress将导出函数的地址加载到变量中,键入为stdcall函数指针,然后调用它.这有点工作.正如我所说,在一些情况下,奇怪的错误消息的一些问题.
好的,这是他们的代码,并特别注意汇编代码的功能.
function CorBindToRuntimeEx(pwszVersion, pwszBuildFlavor: PWideChar;
startupFlags: DWORD; const rclsid: TCLSID; const riid: TIID;
out pv): HRESULT; stdcall;
{$EXTERNALSYM CorBindToRuntimeEx}
...
var
_CorBindToRuntimeEx: Pointer = nil;
function CorBindToRuntimeEx;
begin
GetProcedureAddress(_CorBindToRuntimeEx, mscoree_dll,
'CorBindToRuntimeEx');
asm
mov esp, ebp
pop ebp
jmp [_CorBindToRuntimeEx]
end;
end;
...
OleCheck(CorBindToRuntimeEx(PWideCharOrNil(ClrVer),
PWideChar(ClrHostFlavorNames[Flavor]), Flags,
CLASS_CorRuntimeHost, IID_ICorRuntimeHost,
FDefaultInterface));
Run Code Online (Sandbox Code Playgroud)
请注意,我稍微重新格式化了代码,以避免在SO上出现水平滚动条,但只是为了添加一些换行符和一些缩进,代码就是原样.
最后的调用可能是无关紧要的,它基本上会传递我们所做的相同参数(注意我们传递0作为选项值,但我们也尝试使用Jcl代码使用的相同特定参数,问题仍然存在当下).
所以,我的问题是,汇编代码的作用是什么?我知道它在技术意义上的作用,我以前一直在编程汇编,所以它操纵堆栈指针.
问题是为什么必须这样做.我只是不明白.
难道堆栈帧并不相当 stdcall毕竟?
今天请教我一些东西.
编辑:好的,相应地更改了我的代码,但问题仍然存在,所以不是这样.看起来我毕竟会做一些WinDbg挖掘第三方代码.
汇编代码删除了CorBindToRuntimeEx的堆栈帧.如果调用CorBindToRuntimeEx,则所有参数都被推送到堆栈(=> stdcall).该函数然后调用GetProcedureAddress来初始化全局_CorBindToRuntimeEx变量,该变量现在指向'CorBindToRuntimeEx'函数.
GetProcedureAddress返回后,必须调用_CorBindToRuntimeEx函数.但在这里我们有一个问题.Delphi自动在代码中添加了"push ebp; mov ebp,esp"(其中"begin"为).并且为了删除该堆栈帧,使用"mov esp,ebp; pop ebp".然后,"jmp [_CorBindToRuntimeEx]"将执行指针设置为_CorBindToRuntimeEx函数,该函数然后使用CorBindToRuntimeEx函数的返回地址.