[英]How to Initialize an object from an imported DLL in Delphi?
I built a Class Library (.Net Framework) in C#, named Return that has only one method which returns 1. Then, I called the.Net DLL from a console application in Delphi by turning it COM visible and by importing it as Type Library . 因此,代码是在http://docwiki.embarcadero.com/RADStudio/Sydney/en/Code_Generated_When_You_Import_Type_Library_Information中指定的结果 TypeLibName_TLB 单元 (Return_TLB) 中生成的
目前,我正在尝试使用在 Return_TLB 单元中名为 Function_() 的导入 DLL 中编写的 function Function()。 当我运行该程序时,它显示一个警告:变量“c1”可能尚未初始化。 当我调试程序时,它会抛出异常:异常 class $C0000005 并带有消息“在 0x005ff3c3 处的访问冲突:读取地址 0x00000060”。
我一直在尝试通过使用在 Return_TLB 单元 Create(AOwner:TComponent) 中生成的 TClass1 的构造函数来初始化 c1,但我不明白应该在 AOwner 和 TComponent 中使用什么。 此外,我不确定这是否是正确的程序,如果我错了,请纠正我。
关于抛出的异常,我相信这是因为我试图使用 object 而不先初始化它。
我是 Delphi 的新手,非常感谢您的帮助。
这是我在 C# 中编写的代码:
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Return
{
public class Class1
{
public int Function()
{
return 1;
}
}
}
这是我在 Delphi 中编写的代码:
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.SysUtils,
Return_TLB in 'Return_TLB.pas';
var
i:Integer;
c1:TClass1;
begin
//c1.Create(TObject: TClass1); Trying to initialize c1
i:= c1.Function_();
WriteLn(i);
ReadLn;
end.
这是 Return_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.
// ************************************************************************ //
// $Rev: 52393 $
// File generated on 07/12/2020 21:52:26 from Type Library described below.
// ************************************************************************ //
// Type Lib: C:\Users\jsreb\Documents\MIEB\C-mo\DLL_antigo\Return\Return\bin\Debug\Return.tlb (1)
// LIBID: {02B4AEEB-B3B5-40B5-AFB0-BF7A4420E4FF}
// LCID: 0
// Helpfile:
// HelpString:
// DepndLst:
// (1) v2.0 stdole, (C:\Windows\SysWOW64\stdole2.tlb)
// (2) v2.4 mscorlib, (C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb)
// SYS_KIND: SYS_WIN32
// Errors:
// Hint: Member 'Function' of '_Class1' changed to 'Function_'
// Error creating palette bitmap of (TClass1) : Server mscoree.dll contains no icons
// ************************************************************************ //
{$TYPEDADDRESS OFF} // Unit must be compiled without type-checked pointers.
{$WARN SYMBOL_PLATFORM OFF}
{$WRITEABLECONST ON}
{$VARPROPSETTER ON}
{$ALIGN 4}
interface
uses Winapi.Windows, mscorlib_TLB, System.Classes, System.Variants, System.Win.StdVCL, Vcl.Graphics, Vcl.OleServer, Winapi.ActiveX;
// *********************************************************************//
// 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
ReturnMajorVersion = 1;
ReturnMinorVersion = 0;
LIBID_Return: TGUID = '{02B4AEEB-B3B5-40B5-AFB0-BF7A4420E4FF}';
IID__Class1: TGUID = '{9F546242-F23E-3352-8B36-330792602E41}';
CLASS_Class1: TGUID = '{B24AB9E7-6C6C-3FB6-8948-732135D01A14}';
type
// *********************************************************************//
// Forward declaration of types defined in TypeLibrary
// *********************************************************************//
_Class1 = interface;
_Class1Disp = dispinterface;
// *********************************************************************//
// Declaration of CoClasses defined in Type Library
// (NOTE: Here we map each CoClass to its Default Interface)
// *********************************************************************//
Class1 = _Class1;
// *********************************************************************//
// Interface: _Class1
// Flags: (4560) Hidden Dual NonExtensible OleAutomation Dispatchable
// GUID: {9F546242-F23E-3352-8B36-330792602E41}
// *********************************************************************//
_Class1 = interface(IDispatch)
['{9F546242-F23E-3352-8B36-330792602E41}']
function Get_ToString: WideString; safecall;
function Equals(obj: OleVariant): WordBool; safecall;
function GetHashCode: Integer; safecall;
function GetType: _Type; safecall;
function Function_: Integer; safecall;
property ToString: WideString read Get_ToString;
end;
// *********************************************************************//
// DispIntf: _Class1Disp
// Flags: (4560) Hidden Dual NonExtensible OleAutomation Dispatchable
// GUID: {9F546242-F23E-3352-8B36-330792602E41}
// *********************************************************************//
_Class1Disp = dispinterface
['{9F546242-F23E-3352-8B36-330792602E41}']
property ToString: WideString readonly dispid 0;
function Equals(obj: OleVariant): WordBool; dispid 1610743809;
function GetHashCode: Integer; dispid 1610743810;
function GetType: _Type; dispid 1610743811;
function Function_: Integer; dispid 1610743812;
end;
// *********************************************************************//
// The Class CoClass1 provides a Create and CreateRemote method to
// create instances of the default interface _Class1 exposed by
// the CoClass Class1. The functions are intended to be used by
// clients wishing to automate the CoClass objects exposed by the
// server of this typelibrary.
// *********************************************************************//
CoClass1 = class
class function Create: _Class1;
class function CreateRemote(const MachineName: string): _Class1;
end;
// *********************************************************************//
// OLE Server Proxy class declaration
// Server Object : TClass1
// Help String :
// Default Interface: _Class1
// Def. Intf. DISP? : No
// Event Interface:
// TypeFlags : (2) CanCreate
// *********************************************************************//
TClass1 = class(TOleServer)
private
FIntf: _Class1;
function GetDefaultInterface: _Class1;
protected
procedure InitServerData; override;
function Get_ToString: WideString;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure Connect; override;
procedure ConnectTo(svrIntf: _Class1);
procedure Disconnect; override;
function Equals(obj: OleVariant): WordBool;
function GetHashCode: Integer;
function GetType: _Type;
function Function_: Integer;
property DefaultInterface: _Class1 read GetDefaultInterface;
property ToString: WideString read Get_ToString;
published
end;
procedure Register;
resourcestring
dtlServerPage = 'ActiveX';
dtlOcxPage = 'ActiveX';
implementation
uses System.Win.ComObj;
class function CoClass1.Create: _Class1;
begin
Result := CreateComObject(CLASS_Class1) as _Class1;
end;
class function CoClass1.CreateRemote(const MachineName: string): _Class1;
begin
Result := CreateRemoteComObject(MachineName, CLASS_Class1) as _Class1;
end;
procedure TClass1.InitServerData;
const
CServerData: TServerData = (
ClassID: '{B24AB9E7-6C6C-3FB6-8948-732135D01A14}';
IntfIID: '{9F546242-F23E-3352-8B36-330792602E41}';
EventIID: '';
LicenseKey: nil;
Version: 500);
begin
ServerData := @CServerData;
end;
procedure TClass1.Connect;
var
punk: IUnknown;
begin
if FIntf = nil then
begin
punk := GetServer;
Fintf:= punk as _Class1;
end;
end;
procedure TClass1.ConnectTo(svrIntf: _Class1);
begin
Disconnect;
FIntf := svrIntf;
end;
procedure TClass1.DisConnect;
begin
if Fintf <> nil then
begin
FIntf := nil;
end;
end;
function TClass1.GetDefaultInterface: _Class1;
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 TClass1.Create(AOwner: TComponent);
begin
inherited Create(AOwner);
end;
destructor TClass1.Destroy;
begin
inherited Destroy;
end;
function TClass1.Get_ToString: WideString;
begin
Result := DefaultInterface.ToString;
end;
function TClass1.Equals(obj: OleVariant): WordBool;
begin
Result := DefaultInterface.Equals(obj);
end;
function TClass1.GetHashCode: Integer;
begin
Result := DefaultInterface.GetHashCode;
end;
function TClass1.GetType: _Type;
begin
Result := DefaultInterface.GetType;
end;
function TClass1.Function_: Integer;
begin
Result := DefaultInterface.Function_;
end;
procedure Register;
begin
RegisterComponents(dtlServerPage, [TClass1]);
end;
end.```
对于 COM DLL,您首先必须调用Coinitialize(nil);
. 那么由于 TClass1 是一个 class,你必须先调用它的构造函数才能调用它的方法。 完成后,您必须释放您创建的实例。 完成 COM 后,您必须调用CoUninitialize()
,通常在程序结束时调用。
var
c1 : TClass1;
i : Integer;
begin
CoInitialize(nil);
c1 := TClass1.Create(nil);
try
i := c1.Function_();
WriteLn(i);
finally
c1.Free;
end;
CoUninitialize();
end;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.