如何在 C# 中调用 Delphi DLL 的事件?

3

Delphi7 test.dll

unit DLLFunction;
interface
uses
  Sysutils, classes,  Dialogs;

type
  TEvent = procedure(index, status, percent: integer) of object; stdcall;
  IMyDll = interface
  ['{42C845F8-F45C-4BC7-8CB5-E76658262C4A}']
    procedure SetEvent(const value: TEvent); stdcall;
  end;

  TMyDllClass = class(TInterfacedObject, IMyDll)
  public
    procedure SetEvent(const value: TEvent); stdcall;
  end;

  procedure CreateDelphiClass(out intf: IMyDll); stdcall;

implementation
procedure TMyDllClass.SetEvent(const value: TEvent); stdcall;
begin
  if Assigned (value) then
  begin
    ShowMessage('Event call');
    value(1,2,3);
  end;
end;
exports
  createDelphiClass;
end.

C#源代码

// event
  public delegate void TEvent(int index, int status, int percent);

  [ComImport, Guid("42C845F8-F45C-4BC7-8CB5-E76658262C4A"),
  InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  public interface IMyDll
  {
    // event
    [MethodImplAttribute(MethodImplOptions.PreserveSig)]
    void SetEvent([MarshalAs(UnmanagedType.FunctionPtr)]TEvent eventCallback);

  }

  class TestInterface
  {
    const string dllPath = "testDelphiDll.DLL";

    [DllImport(dllPath, CharSet = CharSet.Unicode, CallingConvention = CallingConvention.StdCall)]
    public static extern void CreateDelphiClass(out IMyDll dll);

    public IMyDll getDelphiInterface()
    {
      IMyDll mydll = null;
      CreateDelphiClass(out mydll);

      return mydll;
    }
  }

然后在C#中使用
  TestInterface tInterface = new TestInterface();
  delphi = tInterface.getDelphiInterface();

  delphi.SetEvent(delegate(int index, int status, int percent)
  {
    MessageBox.Show("index: " + index.ToString() + "\nstatus: " + status.ToString() + " \npercent: " + percent.ToString());
  });

结果

索引:-19238192731

状态:1

百分比:2

然后应用程序崩溃了。 异常:

未经处理的类型为“System.AccessViolationException”的异常在DLLCallTest.exe中发生。

提示:您尝试读取或写入受保护的内存。在大多数情况下,这表示其他内存已被破坏。

我认为这不是一个问题,但为什么会出现这个异常和错误的参数?

1个回答

4
你的Delphi声明中,TEventof object类型。这与你的C#不匹配。of object方法类型是一个双指针,包含实例引用和代码地址。而你的C#委托是一个单指针,只有代码地址。
移除of object即可使你的程序正常工作。

如果我使用 'of object',那么如何在C#中使用委托? - InKwon Devik Kim
没有支持的方法,你必须进行黑客攻击。 - David Heffernan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接