Luk*_*sky 18 .net c# delphi clr host
有人可以在这里发布一个如何在Delphi中托管CLR的例子吗?我在这里读过类似的问题,但我不能使用JCL,因为我想在Delphi 5中托管它.谢谢.
编辑:这文章关于福克斯临托管CLR看起来很有希望,但我不知道如何从德尔福访问clrhost.dll.
编辑2:我放弃了Delphi 5的要求.现在我正在尝试使用Delphi 7进行JCL.但是我再也找不到任何示例.这就是我现在所拥有的:
我的C#程序集:
namespace DelphiNET
{
public class NETAdder
{
public int Add3(int left)
{
return left + 3;
}
}
}
Run Code Online (Sandbox Code Playgroud)
我把它编译成了DelphiNET.dll.
现在我想使用Delphi的这个程序集:
uses JclDotNet, mscorlib_TLB;
procedure TForm1.Button1Click(Sender: TObject);
var
clr: TJclClrHost;
ads: TJclClrAppDomainSetup;
ad: TJclClrAppDomain;
ass: TJclClrAssembly;
obj: _ObjectHandle;
ov: OleVariant;
begin
clr := TJclClrHost.Create();
clr.Start;
ads := clr.CreateDomainSetup;
ads.ApplicationBase := 'C:\Delhi.NET';
ads.ConfigurationFile := 'C:\Delhi.NET\my.config';
ad := clr.CreateAppDomain('myNET', ads);
obj := (ad as _AppDomain).CreateInstanceFrom('DelphiNET.dll', 'DelphiNET.NETAdder');
ov := obj.Unwrap;
Button1.Caption := 'done ' + string(ov.Add3(5));
end;
Run Code Online (Sandbox Code Playgroud)
这以错误结束:EOleError:Variant不引用自动化对象
我已经很久没和德尔福合作了,所以我被困在这里......
解决方案: COM可见性存在问题,默认情况下不存在.这是正确的.NET程序集:
namespace DelphiNET
{
[ComVisible(true)]
public class NETAdder
{
public int Add3(int left)
{
return left + 3;
}
}
}
Run Code Online (Sandbox Code Playgroud)
使用Delphi中的.NET时,重要Set8087CW($133F);的是在程序开始时(即之前Application.Initialize;)调用.Delphi默认启用浮点异常(请参阅此内容),CLR不喜欢它们.当我启用它们时,我的程序奇怪地冻结了.
Rob*_*cke 12
这是另一种选择.
这是C#代码.即使你不想使用我的非托管导出,它仍然会解释如何使用mscoree(CLR托管的东西)而不通过IDispatch(IDispatch非常慢).
using System;
using System.Collections.Generic;
using System.Text;
using RGiesecke.DllExport;
using System.Runtime.InteropServices;
namespace DelphiNET
{
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[Guid("ACEEED92-1A35-43fd-8FD8-9BA0F2D7AC31")]
public interface IDotNetAdder
{
int Add3(int left);
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
public class DotNetAdder : DelphiNET.IDotNetAdder
{
public int Add3(int left)
{
return left + 3;
}
}
internal static class UnmanagedExports
{
[DllExport("createdotnetadder", CallingConvention = System.Runtime.InteropServices.CallingConvention.StdCall)]
static void CreateDotNetAdderInstance([MarshalAs(UnmanagedType.Interface)]out IDotNetAdder instance)
{
instance = new DotNetAdder();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是Delphi接口声明:
type
IDotNetAdder = interface
['{ACEEED92-1A35-43fd-8FD8-9BA0F2D7AC31}']
function Add3(left : Integer) : Integer; safecall;
end;
Run Code Online (Sandbox Code Playgroud)
如果使用非托管导出,则可以这样做:
procedure CreateDotNetAdder(out instance : IDotNetAdder); stdcall;
external 'DelphiNET' name 'createdotnetadder';
var
adder : IDotNetAdder;
begin
try
CreateDotNetAdder(adder);
Writeln('4 + 3 = ', adder.Add3(4));
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
end.
Run Code Online (Sandbox Code Playgroud)
当我调整Lars的样本时,它看起来像这样:
var
Host: TJclClrHost;
Obj: IDotNetAdder;
begin
try
Host := TJclClrHost.Create;
Host.Start();
WriteLn('CLRVersion = ' + Host.CorVersion);
Obj := Host.DefaultAppDomain
.CreateInstance('DelphiNET',
'DelphiNET.DotNetAdder')
.UnWrap() as IDotNetAdder;
WriteLn('2 + 3 = ', Obj.Add3(2));
Host.Stop();
except
on E: Exception do
Writeln(E.Classname, ': ', E.Message);
end;
end.
Run Code Online (Sandbox Code Playgroud)
在这种情况下,您可以从C#代码中删除"UnmanagedExports"类,当然.
这堂课必须是可见的.如果您对整个程序集具有ComVisible(false),则可能不是这种情况.
默认情况下.Net类将与IDispatch兼容,因此如果类真的是可见的,那么你的样本应该可以正常工作.
但首先将它剥离到最低限度.将您的exe放在与.Net程序集相同的文件夹中,并跳过配置文件和应用程序库.
在事情变得混乱之前,这里发生了异常,对吧?
ov := obj.Unwrap;
Run Code Online (Sandbox Code Playgroud)
干得好:
program CallDotNetFromDelphiWin32;
{$APPTYPE CONSOLE}
uses
Variants, JclDotNet, mscorlib_TLB, SysUtils;
var
Host: TJclClrHost;
Obj: OleVariant;
begin
try
Host := TJclClrHost.Create;
Host.Start;
WriteLn('CLRVersion = ' + Host.CorVersion);
Obj := Host.DefaultAppDomain.CreateInstance('DelphiNET', 'DelphiNET.NETAdder').UnWrap;
WriteLn('2 + 3 = ' + IntToStr(Obj.Add3(2)));
Host.Stop;
except
on E: Exception do
Writeln(E.Classname, ': ', E.Message);
end;
end.
Run Code Online (Sandbox Code Playgroud)
注意:假设DelphiNET.NET中的DelphiNET.NETAdder类型和Add3方法是ComVisible.感谢罗伯特.
更新:
使用反射时,您不需要ComVisible属性.下一个例子即使不是ComVisible也可以工作.
Assm := Host.DefaultAppDomain.Load_2('NetAddr');
T := Assm.GetType_2('DelphiNET.NETAdder');
Obj := T.InvokeMember_3('ctor', BindingFlags_CreateInstance, nil, null, nil);
Params := VarArrayOf([2]);
WriteLn('2 + 3 = ' + IntToStr(T.InvokeMember_3('Add3', BindingFlags_InvokeMethod, nil, Obj, PSafeArray(VarArrayAsPSafeArray(Params)))));
Run Code Online (Sandbox Code Playgroud)