Возможно ли создать COM-объект?


#1

Собсна, сабж.

Возможно ли в PascalABC создавать com-объекты? Не нашёл такого вопроса на форуме и в примерах ничего похожего тоже откопать не удалось.


#2

Приведите примеры в любом другом языке. Желательно на C#, тогда строчка в строчку можно будет перевести.


#3

Сам я на c# не умею. Гугль показал вот такой пример.

https://aakinshin.net/ru/posts/wrap-cs-in-com/


#4

Больше всего там мне понравилось

Класс и интерфейс нужно пометить рядом атрибутов: следует указать для них уникальные GUID-ы,

GUID - это такая штука, которую сделать уникальной - это еще потрудиться нужно. Вовсе не факт, что завтра при попытке поставить на компьютер какое-то программное обеспечение, там не попадется аналогичный GUID. Вероятность небольшая, но она есть…


#5

Вы предлагаете обсудить достоинства и недостатки технологии COM?


#6

А смысл под .NET играться в COM ?


#7

Это философский вопрос, который выходит за рамки данного топика. Меня интересует, возможно ли создать COM-объект. Обсуждать причины этого интереса я здесь не стану.


#8
[Guid("364C5E66-4412-48E3-8BD8-7B2BF09E8922")]
[ComVisible(true)]
public interface ICalculator
{
    int Sum(int a, int b);
}

[Guid("8C034F6A-1D3F-4DB8-BC99-B73873D8C297")]
[ClassInterface(ClassInterfaceType.None)]
[ComVisible(true)]
public class Calculator : ICalculator
{
    public int Sum(int a, int b)
    {
        return a + b;
    }
}

Как и обещал, строчка в строчку:

type
  [System.Runtime.InteropServices.Guid('364C5E66-4412-48E3-8BD8-7B2BF09E8922')]
  [System.Runtime.InteropServices.ComVisible(true)]
  ICalculator=interface
    function Sum(a, b:integer): integer;
  end;
  
  [System.Runtime.InteropServices.Guid('8C034F6A-1D3F-4DB8-BC99-B73873D8C297')]
  [System.Runtime.InteropServices.ClassInterface(System.Runtime.InteropServices.ClassInterfaceType.None)]
  [System.Runtime.InteropServices.ComVisible(true)]
  Calculator=class(ICalculator)
    public function Sum(a, b:integer): integer;
    begin
      Result := a+b;
    end;
  end;

begin end.

System.Runtime.InteropServices можно ещё в uses засунуть, чтоб не писать каждый раз.

Но вопрос надобности действительно важен. Какой именно функционал вам нужен? Возможно, есть инструмент лучше, поэтому вас и спрашивают. И дело совсем не в философии.


#9

Руководство поставило задачу исследовать возможность перевести старый написанный на Delphi проект на .NET.


#10

COMTest.pas

{$reference 'System.Windows.Forms.dll'}

uses 
  System.Runtime.InteropServices,
  System.Windows.Forms;

const
  IID_ITest = '9dd61649-5842-4df0-93c9-d958e071eb65';
  CLASS_Test = 'a639c938-9088-4675-a144-82f72dc60f23';

type
  [Guid(IID_ITest), ComVisible(true)]  
  ITest = interface
    [DispId(1)]
    procedure HelloWorld(Name: String);
  end;
  
  [Guid(CLASS_Test), ClassInterface(ClassInterfaceType.None), ComVisible(true), ProgId('COMTest.TCOMTest')]
  TCOMTest = class(ITest)
    public procedure HelloWorld(Name: String);
    begin
      MessageBox.Show('Hello, my name is ' + Name);
    end;
  end;

begin
  
end.

ClientTest.pas:

program ClientTest;

uses
  System.Runtime.InteropServices,
  System.Reflection;

begin
  var t: System.Type = System.Type.GetTypeFromProgID('COMTest.TCOMTest');
  var o: System.object = System.Activator.CreateInstance(t);
  
end.

COMTest компилируется, полученный exe-шник регистрирую в системе с помощью regasm, который говорит об успешной регистрации. Также в реестре в соотв.ветках появляются записи. Обратиться после этого к нему не удаётся. ClientTest выдаёт ошибку: ClientTest.pas(9) : Ошибка времени выполнения: Не удалось получить фабрику класса COM для компонента с CLSID {A639C938-9088-4675-A144-82F72DC60F23} из-за следующей ошибки: 80040154 Класс не зарегистрирован (Исключение из HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG)).

Гугль намекает, что мы из 64-битного проекта пытаемся дёрнуть 32-битный COM-объект.

Отсюда вопрос: можно ли паскалю намекнуть, что мы хотим собрать x86-программу?

PS. Из Delphi COM вызвался.


#11

Давайте вы всё же определитесь, зачем вам это нужно. Потому что то что вы делаете пока что - лучше делать через библиотеки.


#12

{$platformtarget x86}


#13

Спасибо.