Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Dll на C# запустить из Delphi  [new]
BorodaOleg
Member

Откуда:
Сообщений: 74
Имеется в наличии DLL писаное на C# (суммирует 2 цифери)
Нужно запустить ее из Delhpi

unit calc;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, MyLibrary_TLB, StdCtrls, ActiveX;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    calc :  TCalculator;
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var val : Integer;
begin
  CoInitialize(nil);
  calc := TCalculator.Create(self);
  try
    val := calc.Sum(1,2{StrToInt(Edit1.Text), StrToInt(Edit2.Text)});
    Label1.Caption := IntToStr(val);
  finally
    calc.Free;
  end;
  CoUninitialize();
end;

end.


и собственно сгенерированный Дельфёй модуль:

unit MyLibrary_TLB;

// ************************************************************************ //
// WARNING                                                                    
// -------                                                                    
// The types declared in this file were generated from data read from a       
// Type Library. If this type library is explicitly or indirectly (via        
// another type library referring to this type library) re-imported, or the   
// 'Refresh' command of the Type Library Editor activated while editing the   
// Type Library, the contents of this file will be regenerated and all        
// manual modifications will be lost.                                         
// ************************************************************************ //

// PASTLWTR : 1.2
// File generated on 09.06.2021 10:51:58 from Type Library described below.

// ************************************************************************  //
// Type Lib: C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\MyLib.tlb (1)
// LIBID: {30D25254-797F-4DE3-9C7C-8EE3DB81049D}
// LCID: 0
// Helpfile: 
// HelpString: 
// DepndLst: 
//   (1) v2.0 stdole, (C:\WINDOWS\system32\stdole2.tlb)
//   (2) v2.4 mscorlib, (C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb)
// Errors:
//   Error creating palette bitmap of (TCalculator) : Server mscoree.dll contains no icons
// ************************************************************************ //
// *************************************************************************//
// NOTE:                                                                      
// Items guarded by $IFDEF_LIVE_SERVER_AT_DESIGN_TIME are used by properties  
// which return objects that may need to be explicitly created via a function 
// call prior to any access via the property. These items have been disabled  
// in order to prevent accidental use from within the object inspector. You   
// may enable them by defining LIVE_SERVER_AT_DESIGN_TIME or by selectively   
// removing them from the $IFDEF blocks. However, such items must still be    
// programmatically created via a method of the appropriate CoClass before    
// they can be used.                                                          
{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers. 
{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}
{$VARPROPSETTER ON}
interface

uses Windows, ActiveX, Classes, Graphics, mscorlib_TLB, OleServer, StdVCL, Variants;
  


// *********************************************************************//
// GUIDS declared in the TypeLibrary. Following prefixes are used:        
//   Type Libraries     : LIBID_xxxx                                      
//   CoClasses          : CLASS_xxxx                                      
//   DISPInterfaces     : DIID_xxxx                                       
//   Non-DISP interfaces: IID_xxxx                                        
// *********************************************************************//
const
  // TypeLibrary Major and minor versions
  MyLibraryMajorVersion = 1;
  MyLibraryMinorVersion = 0;

  LIBID_MyLibrary: TGUID = '{30D25254-797F-4DE3-9C7C-8EE3DB81049D}';

  IID_ICalculator: TGUID = '{364C5E66-4412-48E3-8BD8-7B2BF09E8922}';
  CLASS_Calculator: TGUID = '{8C034F6A-1D3F-4DB8-BC99-B73873D8C297}';
type

// *********************************************************************//
// Forward declaration of types defined in TypeLibrary                    
// *********************************************************************//
  ICalculator = interface;
  ICalculatorDisp = dispinterface;

// *********************************************************************//
// Declaration of CoClasses defined in Type Library                       
// (NOTE: Here we map each CoClass to its Default Interface)              
// *********************************************************************//
  Calculator = ICalculator;


// *********************************************************************//
// Interface: ICalculator
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      {364C5E66-4412-48E3-8BD8-7B2BF09E8922}
// *********************************************************************//
  ICalculator = interface(IDispatch)
    ['{364C5E66-4412-48E3-8BD8-7B2BF09E8922}']
    function Sum(a: Integer; b: Integer): Integer; safecall;
  end;

// *********************************************************************//
// DispIntf:  ICalculatorDisp
// Flags:     (4416) Dual OleAutomation Dispatchable
// GUID:      {364C5E66-4412-48E3-8BD8-7B2BF09E8922}
// *********************************************************************//
  ICalculatorDisp = dispinterface
    ['{364C5E66-4412-48E3-8BD8-7B2BF09E8922}']
    function Sum(a: Integer; b: Integer): Integer; dispid 1610743808;
  end;

// *********************************************************************//
// The Class CoCalculator provides a Create and CreateRemote method to          
// create instances of the default interface ICalculator exposed by              
// the CoClass Calculator. The functions are intended to be used by             
// clients wishing to automate the CoClass objects exposed by the         
// server of this typelibrary.                                            
// *********************************************************************//
  CoCalculator = class
    class function Create: ICalculator;
    class function CreateRemote(const MachineName: string): ICalculator;
  end;


// *********************************************************************//
// OLE Server Proxy class declaration
// Server Object    : TCalculator
// Help String      : 
// Default Interface: ICalculator
// Def. Intf. DISP? : No
// Event   Interface: 
// TypeFlags        : (2) CanCreate
// *********************************************************************//
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
  TCalculatorProperties= class;
{$ENDIF}
  TCalculator = class(TOleServer)
  private
    FIntf:        ICalculator;
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
    FProps:       TCalculatorProperties;
    function      GetServerProperties: TCalculatorProperties;
{$ENDIF}
    function      GetDefaultInterface: ICalculator;
  protected
    procedure InitServerData; override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor  Destroy; override;
    procedure Connect; override;
    procedure ConnectTo(svrIntf: ICalculator);
    procedure Disconnect; override;
    function Sum(a: Integer; b: Integer): Integer;
    property DefaultInterface: ICalculator read GetDefaultInterface;
  published
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
    property Server: TCalculatorProperties read GetServerProperties;
{$ENDIF}
  end;

{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
// *********************************************************************//
// OLE Server Properties Proxy Class
// Server Object    : TCalculator
// (This object is used by the IDE's Property Inspector to allow editing
//  of the properties of this server)
// *********************************************************************//
 TCalculatorProperties = class(TPersistent)
  private
    FServer:    TCalculator;
    function    GetDefaultInterface: ICalculator;
    constructor Create(AServer: TCalculator);
  protected
  public
    property DefaultInterface: ICalculator read GetDefaultInterface;
  published
  end;
{$ENDIF}


procedure Register;

resourcestring
  dtlServerPage = 'ActiveX';

  dtlOcxPage = 'ActiveX';

implementation

uses ComObj;

class function CoCalculator.Create: ICalculator;
begin
  Result := CreateComObject(CLASS_Calculator) as ICalculator;
end;

class function CoCalculator.CreateRemote(const MachineName: string): ICalculator;
begin
  Result := CreateRemoteComObject(MachineName, CLASS_Calculator) as ICalculator;
end;

procedure TCalculator.InitServerData;
const
  CServerData: TServerData = (
    ClassID:   '{8C034F6A-1D3F-4DB8-BC99-B73873D8C297}';
    IntfIID:   '{364C5E66-4412-48E3-8BD8-7B2BF09E8922}';
    EventIID:  '';
    LicenseKey: nil;
    Version: 500);
begin
  ServerData := @CServerData;
end;

procedure TCalculator.Connect;
var
  punk: IUnknown;
begin
  if FIntf = nil then
  begin
    punk := GetServer;
    Fintf:= punk as ICalculator;
  end;
end;

procedure TCalculator.ConnectTo(svrIntf: ICalculator);
begin
  Disconnect;
  FIntf := svrIntf;
end;

procedure TCalculator.DisConnect;
begin
  if Fintf <> nil then
  begin
    FIntf := nil;
  end;
end;

function TCalculator.GetDefaultInterface: ICalculator;
begin
  if FIntf = nil then
    Connect;
  Assert(FIntf <> nil, 'DefaultInterface is NULL. Component is not connected to Server. You must call ''Connect'' or ''ConnectTo'' before this operation');
  Result := FIntf;
end;

constructor TCalculator.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
  FProps := TCalculatorProperties.Create(Self);
{$ENDIF}
end;

destructor TCalculator.Destroy;
begin
{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
  FProps.Free;
{$ENDIF}
  inherited Destroy;
end;

{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
function TCalculator.GetServerProperties: TCalculatorProperties;
begin
  Result := FProps;
end;
{$ENDIF}

function TCalculator.Sum(a: Integer; b: Integer): Integer;
begin
  Result := DefaultInterface.Sum(a, b);
end;

{$IFDEF LIVE_SERVER_AT_DESIGN_TIME}
constructor TCalculatorProperties.Create(AServer: TCalculator);
begin
  inherited Create;
  FServer := AServer;
end;

function TCalculatorProperties.GetDefaultInterface: ICalculator;
begin
  Result := FServer.DefaultInterface;
end;

{$ENDIF}

procedure Register;
begin
  RegisterComponents(dtlServerPage, [TCalculator]);
end;

end.


Запускается, но в момент выполнения на строке val := calc.Sum(1,2{StrToInt(Edit1.Text), StrToInt(Edit2.Text)}); влетает в TCalculator.Connect; и на строке punk := GetServer; пишет ошибку: "Не удается найти указанный файл".
Как с этим бороться, подскажите...
9 июн 21, 11:23    [22333186]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
Кроик Семён
Member

Откуда: СПб --> Dortmund
Сообщений: 6747
64-битные COM-обьекты не совместимы с 32-битным приложением. Вот и не находит тогда DLL с подходящей разрядностью.

У вас какая где разрядность?

Сообщение было отредактировано: 9 июн 21, 11:40
9 июн 21, 11:46    [22333194]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
b0rk
Member

Откуда: Харьков
Сообщений: 609
автор
я не знаю, но может ли такое быть, что, к примеру, 64-битные COM-обьекты не совместимы с 32-битным приложением.

Конечно не совместимы.
В случае с C# можно сделать одну DLL для 32 и 64 битных платформ.
И не забыть зарегестрировать COM объект из DLL в системе.
9 июн 21, 11:50    [22333198]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
BorodaOleg
Member

Откуда:
Сообщений: 74
Кроик Семён, b0rk

Компилировалось на Win10, используется на WinXP
Возможно баг в этом
9 июн 21, 11:55    [22333203]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
b0rk
Member

Откуда: Харьков
Сообщений: 609
еще можно использовать NuGet пакет UnmanagedExports, чтобы добавить в DLL писаную на C# экспорт unmanaged функций. в этом случае можно обойтись без COM объектов, а грузить эту DLL через LoadLibrary и получать интерфейс через экспортированую unmanaged функцию.
правда при этом подходе прийдется делать две DLL - одну для 32 и вторую для 64 бит.
9 июн 21, 11:56    [22333204]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
b0rk
Member

Откуда: Харьков
Сообщений: 609
BorodaOleg

Компилировалось на Win10, используется на WinXP
Возможно баг в этом

WinXP и .NET это конечно жесть. Для начала надо проверить, что .NET Framework используемый в DLL поддерживает WinXP и установлен на WinXP.
Кроме того DLL с COM объетом нельзя просто скопировать. Надо зарегестрировать COM объект системе.
Я бы начал с того, что сделал бы простенькое .NET приложение, которое грузит эту DLL и проверил, что это приложение запускается на WinXP. А потом уже стал бы пробовать грузить эту DLL в Delphi.

Сообщение было отредактировано: 9 июн 21, 11:55
9 июн 21, 12:01    [22333208]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
BorodaOleg
Member

Откуда:
Сообщений: 74
b0rk
BorodaOleg

Компилировалось на Win10, используется на WinXP
Возможно баг в этом

WinXP и .NET это конечно жесть. Для начала надо проверить, что .NET Framework используемый в DLL поддерживает WinXP и установлен на WinXP.
Кроме того DLL с COM объетом нельзя просто скопировать. Надо зарегестрировать COM объект системе.
Я бы начал с того, что сделал бы простенькое .NET приложение, которое грузит эту DLL и проверил, что это приложение запускается на WinXP. А потом уже стал бы пробовать грузить эту DLL в Delphi.


Перекомпилировали под W32 - эффект тот же.
DLL с COM объектом регестрировали, в принципе если бы не регистрировали не создалась бы tlb-шка
Бум пробовать создать приложение на C# и запускать ее под XP...
9 июн 21, 12:32    [22333228]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
Мимопроходящий
Member

Откуда: бурятский тундрюк, эсквайр
Сообщений: 32405

09.06.2021 12:32, BorodaOleg пишет:
> Бум пробовать создать приложение на C# и запускать ее под XP...

для начала проверь, какие версии (т)очко.нет-а установлены на этой ХР

Posted via ActualForum NNTP Server 1.5

9 июн 21, 12:35    [22333231]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
BorodaOleg
Member

Откуда:
Сообщений: 74
Мимопроходящий

09.06.2021 12:32, BorodaOleg пишет:
> Бум пробовать создать приложение на C# и запускать ее под XP...

для начала проверь, какие версии (т)очко.нет-а установлены на этой ХР


К сообщению приложен файл. Размер - 110Kb
9 июн 21, 12:41    [22333237]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 12901
Кроик Семён
64-битные COM-обьекты не совместимы с 32-битным приложением.
С прямыми руками очень даже совместимы. Сейчас именно так вызываю из 32-битного приложения на Делфи 64-битную библиотеку на C++
9 июн 21, 12:49    [22333240]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
Dimitry Sibiryakov
Member

Откуда:
Сообщений: 53472

BorodaOleg
в принципе если бы не регистрировали не создалась бы tlb-шка

Эти два процесса никак не связаны.

Posted via ActualForum NNTP Server 1.5

9 июн 21, 12:49    [22333241]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
BorodaOleg
Member

Откуда:
Сообщений: 74
Dimitry Sibiryakov

BorodaOleg
в принципе если бы не регистрировали не создалась бы tlb-шка

Эти два процесса никак не связаны.


Усёк
9 июн 21, 13:06    [22333249]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
BorodaOleg
Member

Откуда:
Сообщений: 74
Сделали проект на C#, запустился, всё работает
Delphi по прежнему пишет "Не удается найти указанный файл"

Пробежал дебагером, уходит в Windows с функцией OleCheck(CoCreateInstance(ClassID, nil, CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER, IUnknown, Result)); - и оттуда вываливается с ошибкой

Не могу догнать, что за файл ему нужен

Сообщение было отредактировано: 9 июн 21, 13:12
9 июн 21, 13:19    [22333264]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
BorodaOleg
Member

Откуда:
Сообщений: 74
BorodaOleg
Dimitry Sibiryakov

пропущено...

Эти два процесса никак не связаны.


Усёк


Хотя, если бы я не зарегистрировал объект через RegAsm то он бы не отобразился в Delphi "Import Type Library", и соответственно не было бы возможно создать TLB
9 июн 21, 13:25    [22333271]     Ответить | Цитировать Сообщить модератору
 Re: Dll на C# запустить из Delphi  [new]
BorodaOleg
Member

Откуда:
Сообщений: 74
Всё, запустилось.... Пока были глюки изменили имя с MyLib на MyLibrary, а в каталог с программой MyLibrary.dll скопировать забыли.
:)
Пора в отпуск...
9 июн 21, 13:32    [22333276]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить