Hosting the .NET runtime in a Delphi Program

I was looking into using some .NET code from within a Delphi program, I will need to make my program extensible using .net assemblies and predefined functions (I already support regular DLLs).

After a lot of searching online, I found Managed-VCL, but I'm not ready to pay $250 for what I need, I also found some newsgroups with code that's incomplete and doesn't work.

I'm using Delphi 2007 for win32. What can I use to dynamically execute a function from an assembly with predefined parameters?

Something like:

procedure ExecAssembly(AssemblyFileName:String; Parameters: Variant);

I just want to add that I need to be able to load an arbitrary assemblies (maybe all the assemblies in a specific folder), so creating a C# wrapper may not work.


In the Jedi Code Library (JCL) - free - there is a JclDotNet.pas, containing a class TJclClrHost, probably doing what you want:

  TJclClrHost = class(TJclClrBase, ICorRuntimeHost)
  private
    FDefaultInterface: ICorRuntimeHost;
    FAppDomains: TObjectList;
    procedure EnumAppDomains;
    function GetAppDomain(const Idx: Integer): TJclClrAppDomain;
    function GetAppDomainCount: Integer;
    function GetDefaultAppDomain: IJclClrAppDomain;
    function GetCurrentAppDomain: IJclClrAppDomain;
  protected
    function AddAppDomain(const AppDomain: TJclClrAppDomain): Integer;
    function RemoveAppDomain(const AppDomain: TJclClrAppDomain): Integer; 
  public
    constructor Create(const ClrVer: WideString = '';
      const Flavor: TJclClrHostFlavor = hfWorkStation;
      const ConcurrentGC: Boolean = True;
      const LoaderFlags: TJclClrHostLoaderFlags = [hlOptSingleDomain]);
    destructor Destroy; override;
    procedure Start;
    procedure Stop;
    procedure Refresh;
    function CreateDomainSetup: TJclClrAppDomainSetup;
    function CreateAppDomain(const Name: WideString;
      const Setup: TJclClrAppDomainSetup = nil;
      const Evidence: IJclClrEvidence = nil): TJclClrAppDomain;
    function FindAppDomain(const Intf: IJclClrAppDomain; var Ret: TJclClrAppDomain): Boolean; overload;
    function FindAppDomain(const Name: WideString; var Ret: TJclClrAppDomain): Boolean; overload;
    class function CorSystemDirectory: WideString;
    class function CorVersion: WideString;
    class function CorRequiredVersion: WideString;
    class procedure GetClrVersions(VersionNames: TWideStrings); overload;
    class procedure GetClrVersions(VersionNames: TStrings); overload;
    property DefaultInterface: ICorRuntimeHost read FDefaultInterface implements ICorRuntimeHost;
    property AppDomains[const Idx: Integer]: TJclClrAppDomain read GetAppDomain; default;
    property AppDomainCount: Integer read GetAppDomainCount;
    property DefaultAppDomain: IJclClrAppDomain read GetDefaultAppDomain;
    property CurrentAppDomain: IJclClrAppDomain read GetCurrentAppDomain;
  end;

Hosting the CLR yourself is not all that difficult (especially if you are just using a single AppDomain). You can use the COM based hosting APIs to start up the runtime, load assemblies, create objects and invoke methods on them.

There is a lot of info online, for example the MSDN documentation on "Hosting the Common Language Runtime". (new home)


I can tell you from first hand experience that inter-operating with .Net from Delphi is no picnic. I am a .Net guy, but worked in a .Net and Delphi shop for a while. I managed several projects that were written in .Net (WinForms and WPF) but were called by Delphi. Our Delphi guys had written an interop layer for Delphi to call out to .Net libraries since all of our new products were being written in .Net. It was trouble for us (and these were good Delphi developers). If we could have purchased a good 3rd party library to do the interop for us, it would have been more than worth it. I bet we spent thousands of dollars in man-hours writing and debugging problems with the interop from Delphi to .Net.

I would take that Managed-VLC library for a test drive to see how well it works. If it lives up to its advertising, then it is easily worth the $250.