为对象的Delphi过程封送c#调用者



我已经找到了答案,但对我想做的事情是消极的:

将方法指针从c#传递到Delphi DLL

是否有可能在c#中调用Delphi对象的委托?因为上面示例中的所有Delphi调用者都是静态的和导出的。我正在使用OleVariant,并希望在c#中使用GetDelegateForFunctionPointer从Delphi对象调用调用者。但是当我尝试时,Delphi事件中的调试器在该方法中中断,然后我得到"试图读取或写入受保护的内存"。

Delphi代码:

TOnEvent = procedure() of object;
TOnEventStdCall = procedure() of object; stdcall;
TSimpleClass = class
FUserControl: OleVariant;
FOnEventHandler : TOnEvent;
FOnEventStdCallHandler : TOnEventStdCall;
constructor Create();  
procedure ProcOnEventStdCall(); stdcall;
end;    
...
constructor TSimpleClass.Create();
begin
FHost := TJclClrHost.Create('v4.0.30319');
FHost.Start;
FUserControl := FHost.DefaultAppDomain.CreateInstance('CSharpLibrary','CSharpLibrary.Init').Unwrap;
FOnEventHandler := nil;
FOnEventStdCallHandler := ProcOnEventStdCall;
FUserControl.SetEvent(LongInt(@FOnEventStdCallHandler), LongInt(self));
end;
procedure TSimpleClass.ProcOnEventStdCall; stdcall;
begin
ShowMessage('Invoked');
if Assigned(FOnEventHandler) then 
FOnEventHandler();               // !!! exception here
end;

和c#代码:

struct TMethod
{
IntPtr pMethod;
IntPtr pInstance;  
}
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void TEvent(IntPtr instance);
private TOnEventStdCall _delphiHandler;
public void SetEvent(Int32 method, Int32 instance)
{
m.pMethod = new IntPtr(method);
m.pInstance = new IntPtr(instance);
_delphiHandler += (TEvent)Marshal.GetDelegateForFunctionPointer(m.pMethod, typeof(TEvent));
}
...
_delphiHandler.Invoke(m.pInstance);

我认为类似的问题是,但没有得到答案:

对象 的pascal/delphi过程的c#等价

我还没有测试代码。然而,在Delphi中,它必须这样做:

type
TOnEvent = procedure() of object;
TSimpleClass = class
FUserControl: OleVariant;
constructor Create();
procedure ProcOnEvent();
end;
procedure EventStdCall(AObj: TObject); stdcall;
var
r   : TMethod;
func: TOnEvent;
begin
r.Data := AObj;
r.Code := @TSimpleClass.ProcOnEvent;
func   := TOnEvent(r);
func(); //Execute
end;
constructor TSimpleClass.Create();
begin
FHost := TJclClrHost.Create('v4.0.30319');
FHost.Start;
FUserControl := FHost.DefaultAppDomain.CreateInstance('CSharpLibrary','CSharpLibrary.Init').Unwrap;
FUserControl.SetEvent(LongInt(@EventStdCall), LongInt(Self));
end;
procedure TSimpleClass.ProcOnEvent;
begin
ShowMessage('Invoked');
end;

对于"Self",您可以在c#中使用Int32。这也适用于EventStdCall方法中TObject类型的参数

最新更新