0

I have created a COM DLL in C# and am using it in Delphi 10 as a COM object. After registering the DLL, it is working fine. But I want to use it without registrating the DLL. How can it be possible?

Below is my C# code:

I have set the ComVisible attribute to true in Assembly.cs:

[assembly: ComVisible(true)]

using System;
using System.Runtime.InteropServices;
    
namespace ComCalculator
{

    [ComVisible(true)]
    [Guid("c0a3a815-fade-4fb3-9c75-f6eff1851e23")]
    public interface ICalculator
    {
        int Add(int a, int b);
    }

    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    [Guid("427754c1-c975-4099-9ff7-df788281d3a8")]
    public class Calculator : ICalculator
    {
        public int Add(int a, int b)
        {
            return a + b;
        }
    }
}

Below is my Delphi code:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, ComObj, ComCalculator_TLB;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    comObject: ICalculator;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
  A, B, Result: Integer;
begin
  A := 10;
  B := 5;
  Result := comObject.Add(A, B);
  ShowMessage('The result is: ' + IntToStr(Result));
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  comObject := CoCalculator.Create;
end;

end.
  • 1
    Registration free COM makes use of manifests embedded in the EXE and on disk or embedded in the COM DLL to match things up. To get started see: [Registration-free COM/DLL?](https://stackoverflow.com/questions/5074563/registration-free-com-dll) – Brian Jun 13 '23 at 14:35
  • https://learn.microsoft.com/en-us/dotnet/framework/interop/registration-free-com-interop – Remy Lebeau Jun 13 '23 at 16:12
  • Thanks for the reply. I followed provided steps but getting error "Class not registered". – Santosh Vishwakarma Jun 14 '23 at 06:52

1 Answers1

0

You can output the C# Com object indirectly via C++. The C# framework is loaded via C++.

C# The COM object is defined.

using System;
using System.Runtime.InteropServices;

namespace CSharp
{
  [ComVisible(true)]
  [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
  [Guid("c0a3a815-fade-4fb3-9c75-f6eff1851e23")]
  public interface ICalculator
  {
    [return:  MarshalAs(UnmanagedType.I4)]
    int Add([MarshalAs(UnmanagedType.I4)] int a, 
            [MarshalAs(UnmanagedType.I4)] int b);
  }
  
  public class Calculator : ICalculator
  {
    public int Add(int a, int b)
    {
        return a + b;
    }
  }
}

C++: The COM object is created, packaged and output.

using namespace CSharp;
using namespace System::Runtime::InteropServices;

#include <vcclr.h>
#include <msclr/gcroot.h>

gcroot <ICalculator^> calc = nullptr;

bool __stdcall func(int& c)
{
  c = 0;
  if (calc.operator ->() == nullptr)
  {
    calc = gcnew Calculator();
  }
  if (calc.operator ->() != nullptr)
  {
    System::IntPtr a = Marshal::GetIUnknownForObject(calc);
    c = (int)a.ToPointer();
    return true;
  
  }
  return false;
}

Delphi: The C++ DLL is loaded. Its export function is called. The COM object is unpacked and used.

uses
  System.SysUtils, Winapi.Windows;

type
  ICalculator=interface(IInterface)
  ['{C0A3A815-FADE-4FB3-9C75-F6EFF1851E23}']
    function Add(a, b: integer): integer; safecall;
  end;
  
  Tfunc = function(var Aif: IInterface): boolean; stdcall;
var
  hDll  : THandle;
  func  : Tfunc;
  i     : integer;
  ifDef : IInterface;
  iCalc : ICalculator;
begin
  try
    hDll := LoadLibrary('CPlus.dll');
    try
      func := GetProcAddress(hdll, 'func');
      if func(ifDef) and 
         Assigned(ifDef) and 
         Supports(ifDef, ICalculator, iCalc) then
      begin
        i := iCalc.Add(5, 10);
        writeln(i);
      end;
    finally
      FreeLibrary(hDll);
      readln(i);
    end;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

If one wants to use several C# COM objects, C++ should provide the C# COM service object through which the specific C# COM objects can be requested.

USauter
  • 295
  • 1
  • 9
  • Why I need to output the C# Com object indirectly via C++. Is it not possible directly? Is it possible by using manifest file? – Santosh Vishwakarma Jun 16 '23 at 09:22
  • @Santosh Vishwakarma In order to use C#, the Dot-Net-Framework must be provided. As the question shows, this task is not easy in Delphi. C++ CLI does this implicitly. A manifest file does not need to be explicitly created. – USauter Jun 17 '23 at 23:15