InKwon Devik Kim
InKwon Devik Kim

Reputation: 347

how to call event of delphi dll at c#?

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# source

// 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;
    }
  }

and then use in 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());
  });

the result

index: -19238192731

status: 1

percent: 2

and then crash application. exception :

An unhandled exception of type 'System.AccessViolationException' occurred in DLLCallTest.exe.

TIP: You attempted to read or write protected memory. In most cases, this indicates that other memory is corrupted.

I think this is not a problem, but why occured this exception and wrong parameter?

Upvotes: 3

Views: 506

Answers (1)

David Heffernan
David Heffernan

Reputation: 612794

Your Delphi declaration of TEvent is of object. That doesn't match your C#. The of object method type is a double pointer holding both the instance reference and the code address. Your C# delegate is a single pointer with the code address.

Remove the of object and your program will work.

Upvotes: 4

Related Questions