我们有自己的粘合层代码thingamajig,它允许我们在win32 delphi程序中托管.NET运行时。这使我们能够随着时间的推移逐步过渡到.NET。
但是,我们经常会遇到一些问题,昨天我在这里看到了一个关于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);
现在,我只需使用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));
请注意,我已经对代码进行了轻微的重新格式化,以避免出现水平滚动条,但是只添加了一些换行符和一些缩进,代码就是这样的。
最后一个调用可能与此无关,它基本上会传递与我们相同的参数(请注意,我们将0作为选项值传递,但我们也使用了JCL代码使用的相同的特定参数,但问题仍然存在)。
所以,我的问题是,汇编程序代码是做什么的?我知道它在技术上做什么,我以前一直在编程汇编,所以它操纵堆栈指针。
问题是为什么必须这样做。我就是不明白。
可能堆栈帧不是
相当地
调用约定
毕竟?
今天请教我点东西。
编辑
:好的,相应地更改了我的代码,但问题仍然存在,所以不是这样。看来我要做一些windbg挖掘第三方代码。