如何在c#中调用delphi dll的事件?

时间:2018-03-16 06:48:22

标签: c# delphi dll

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 个答案:

答案 0 :(得分:4)

您的LSApplicationQueriesSchemes的Delphi声明为TEvent。这与你的C#不匹配。 of object方法类型是一个双指针,同时包含实例引用和代码地址。您的C#委托是带有代码地址的单个指针。

删除of object,您的程序即可运行。