Reputation: 347
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
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