Кто-то может отправить здесь пример, как разместить CLR в Delphi? Я считал подобный вопрос здесь, но я не могу использовать JCL, поскольку я хочу разместить его в Delphi 5.Спасибо.
Править: Эта статья о хостинге CLR в Fox Pro выглядит многообещающей, но я не знаю, как получить доступ к clrhost.dll от Delphi.
Редактирование 2: Я разочаровываюсь в требовании Delphi 5. Теперь я пробую JCL Delphi 7. Но снова я не могу найти любой пример. Вот то, что я имею до настоящего времени:
Мой блок C#:
namespace DelphiNET
{
public class NETAdder
{
public int Add3(int left)
{
return left + 3;
}
}
}
Я скомпилировал его в 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;
Это заканчивается ошибкой: EOleError: Вариант не ссылается на объект автоматизации
Я не работал с Delphi в течение долгого времени, таким образом, я застреваю здесь...
Решение: была проблема в видимости COM, которая не является по умолчанию. Это - корректный блок.NET:
namespace DelphiNET
{
[ComVisible(true)]
public class NETAdder
{
public int Add3(int left)
{
return left + 3;
}
}
}
При работе с.NET от Delphi это - важный вызов Set8087CW($133F);
в начале Вашей программы (т.е. прежде Application.Initialize;
). Delphi включил исключения в операции с плавающей запятой по умолчанию (см. это), и CLR не нравятся они. Когда мне включили их, моя программа, странно замороженная.
Класс должен быть уверен в себе. Что может быть не так, если вы увидите (ложь) для всей сборки.
.NET Classes будет совместимым iDispatch по умолчанию, поэтому ваш образец должен работать совсем хорошо, если класс действительно невидим ..
, но внизу его до минимума. Поместите свой EXE в той же папке, что и узел .NET и пропустить файл конфигурации и прикладную базу.
До чего-то смешивается, исключение раскало здесь, верно?
ov := obj.Unwrap;
Вот еще один вариант.
Это код C #. И даже если вы не хотите использовать мой неуправляемый экспорт , это все равно Объясните, как использовать MSCOREEE (проведение хостинга 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();
}
}
}
Это декларация интерфейса Delphi:
type
IDotNetAdder = interface
['{ACEEED92-1A35-43fd-8FD8-9BA0F2D7AC31}']
function Add3(left : Integer) : Integer; safecall;
end;
Если вы используете неуправляемый экспорт, вы можете сделать это так:
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.
, когда я адаптировать образец Ларса, это будет выглядеть так:
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.
в этом случае вы могли бы Удалите класс «UnmanedExports» из кода C #, конечно.
Здесь вы идете:
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.
Примечание: предполагает, что тип delphinet.netdder и метод ADD3 в delphinet.dll - это . Благодаря Роберт .
Обновление :
При использовании отражения вам не нужен неизбежный атрибут. Следующий пример даже работает, не будучи невидимым.
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)))));