c# - Delphi中如何从导入的DLL中初始化一个对象?
问题描述
我在 C# 中构建了一个名为 Return 的类库(.Net 框架),它只有一个返回 1 的方法。然后,我从 Delphi 中的控制台应用程序调用 .Net DLL,方法是使其 COM 可见并将其导入为类型库. 因此,代码是在http://docwiki.embarcadero.com/RADStudio/Sydney/en/Code_Generated_When_You_Import_Type_Library_Information
中指定的结果 TypeLibName_TLB 单元 (Return_TLB) 中生成的
目前,我正在尝试使用在导入的函数中编写的函数 Function() Return_TLB 单元中名为 Function_() 的 DLL。当我运行该程序时,它会显示一个警告:变量“c1”可能尚未初始化。当我调试程序时,它会引发异常:异常类 $C0000005 带有消息“在 0x005ff3c3 处的访问冲突:读取地址 0x00000060”。
我一直在尝试通过使用在 Return_TLB 单元 Create(AOwner:TComponent) 中生成的 TClass1 的构造函数来初始化 c1,但我不明白应该在 AOwner 和 TComponent 中使用什么。此外,我不确定这是否是正确的程序,如果我错了,请纠正我。
关于抛出的异常,我相信这是因为我试图使用一个对象而不先初始化它。
我是 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 是一个类,你必须先调用它的构造函数才能调用它的方法。完成后,您必须释放您创建的实例。完成 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;
推荐阅读
- r - R:效果包 | 混合效应模型。绘制模型估计
- css - 调整大小时 CSS 网格项不跨越设置的列
- docker - Nginx 在 dockerized react 应用程序中尝试获取子路由时返回 404
- python - python:有时会忽略影响
- python - 在 Tkinter 中更新条目和标签小部件
- ruby-on-rails - Rails 路线出现但抛出 404 错误
- jmeter - Jmeter中的参数化文件/文件夹路径
- oracle - 通过 APEX 从数据库服务器下载文件
- vue.js - 设置 vue.config.js 文件以模拟生产设置(连接两个应用程序)
- vba - 使用 Find 和 Resize 转置值错误