从 COM 指针到记录/如何实现(dotNet 的)Marshal.PtrToStructure 的 Delphi 版本

From COM Pointer to Record / How to do a Delphi version of (dotNet's) Marshal.PtrToStructure

寻求有关如何将指针转换/转换为记录的帮助 - 类似于 dotNet 的 Marshal.PtrToStructure 所做的 - 但使用 Delphi.

详细信息:使用 ActiveX / COM(C++ 中的原始代码)。实现允许捕获 ActveX 控件引发的事件的接口。

其中一个已实现接口的方法签名如下所示:

procedure TIUIX_ObjImplEvent.OnEvent(const pSender: IUIX_Obj;  const pEvent: IUIX_Event);

IUIX_Event 是一个接口(派生自 IDispatch)。有一个 属性 类型为 Param_T 的 Param1。

Param1 包含指向记录类型的指针。

现在,我有 C# 代码,我想将其转换为 Delphi:

public void OnEvent(IUIX_Obj pSender, IUIX_Event pEvent)
{
    //some more code before, and then this part:

    IntPtr outPtr = new IntPtr(pEvent.Param1);
    UIX_NotifyInfo ni = (UIX_NotifyInfo)System.Runtime.InteropServices.Marshal.PtrToStructure(outPtr, typeof(UIX_NotifyInfo));
}

UIX_NotifyInfo 是一条记录 (/struct)。

问题:如何从pEvent.Param1到ni?使用 Delphi:

procedure TIUIX_ObjImplEvent.OnEvent(const pSender: IUIX_Obj;  const pEvent: IUIX_Event);
var
  ni : UIX_NotifyInfo;
begin
  pEvent.Handled := false;

  if (pEvent.Code = e_Notify) then
  begin

    //how to go from pEvent.Param1 to ni like in C#'s PtrToStructure?

    if (ni.nCode = UIX_Notify_BeforeShowPopup) then
    begin
      pEvent.Handled := true;
    end;
  end;
end;

我的猜测是使用 Move 过程,但无论我尝试什么,它都无法编译或崩溃:)

Move(??, ni, SizeOf(UIX_NotifyInfo));

我在大卫回答后添加这个...

这是对上述问题的扩展(寻找如何解决 Marshal.GetObjectForIUnknown)。

我有这个 C# 代码:

public void OnEventMonitor(IUIX_Obj pTarget, IUIX_Event pEvent)
{
  IntPtr outPtr;
  pTarget.QueryImpl(typeof(IUIX_Dialog).GUID, null, out outPtr);
  IUIX_Dialog dlg = (IUIX_Dialog)System.Runtime.InteropServices.Marshal.GetObjectForIUnknown(outPtr);
}

拥有:

IUIX_Event = interface(IDispatch)
IUIX_Obj = interface(IDispatch)
IUIX_Dialog = interface(IUIX_ObjImpl) (IDispatch)

我的 Delphi 代码(dlg:IUIX_Dialog,pImpl:指针):

pTarget.QueryImpl(GetTypeData(TypeInfo(IUIX_Dialog)).Guid, nil, @pImpl);
Move(pImpl, dlg, SizeOf(IUIX_Dialog));

以上确实有效。

有更好的方法还是正确的方法?

在非托管代码中很简单,只是一个赋值。

var
  Rec: TMyRec;
  Ptr: Pointer;
.... 
Rec := TMyRec(Ptr^);