.NET与Delphi跨语言回调实现指南

在现代软件开发中,跨语言调用和回调机制是实现不同编程语言间交互的重要手段。本文将介绍如何将.NET方法暴露给Delphi应用程序,并实现跨语言的回调功能。

什么是回调

回调是一种编程模式,允许一个较低级别的软件层调用一个在较高级别定义的子程序(或函数)。在.NET中,通常使用委托(delegate)来实现这一概念。但是,如何在原生代码和.NET之间传递回调呢?本文将解答这个问题。

使.NET方法对原生代码可见

要使.NET方法对原生代码可见,需要将.NET程序集注册为COM对象,并将其放置在全局程序集缓存(GAC)中。以下是一些关键步骤:

  • 注册程序集作为COM对象。
  • 如果需要从不同路径/位置调用,则将程序集放置在全局程序集缓存(GAC)中。
  • 如果需要将程序集添加到GAC,则需要给程序集一个强名称。

.NET部分

将使用Visual Studio 2010和C#来构建.NET部分。首先,添加一个新的类库项目,并将其命名为CSDemoLibrary。在项目属性中,确保设置此库为COM可见。

为了将程序集添加到GAC,需要给程序集一个强名称。在“签名”选项卡中勾选“签名程序集”,然后从下拉列表中选择“新建…”,并命名文件为CSDemoLibrary。

由于需要传递此程序集的指针,因此还有一个额外的步骤,即在构建选项卡中勾选“允许不安全代码”。

首先,定义一个委托来表示回调函数:

public delegate void NativeCallback(Int32 intParam, [MarshalAs(UnmanagedType.LPWStr)] string strParam);

然后,创建一个类并使用ComVisible(true)属性使其COM可见。由于这个方法将处理原生指针(回调指针),还需要使用unsafe关键字标记它:

[ComVisible(true), GuidAttribute("3A65D04A-3F2F-4CB3-B65A-8D402B8C64CE")] public class MyClass { public unsafe int Process(int intValue, IntPtr callbackPointer, int intParam, string strParam) { NativeCallback callbackMethod = (NativeCallback)Marshal.GetDelegateForFunctionPointer(callbackPointer, typeof(NativeCallback)); callbackMethod(intParam, strParam); // 模拟长时间运行的过程 Thread.Sleep(1000); return intValue * 10; } }

注册.NET程序集

为了避免路径问题,可以使用Visual Studio命令提示符。使用此工具,可以通过以下步骤注册COM程序集:

  1. 以管理员身份运行Visual Studio命令提示符。
  2. 使用常规DOS命令导航到CSDemoLibrary.dll文件夹。
  3. 如果打算将.NET库CSDemoLibrary.dll与原生应用程序(.exe)放在同一目录下,则可以忽略将程序集添加到GAC的步骤。否则,应将其添加到GAC,并使用gacutil工具,如下所示:
  4. gacutil -i CSDemoLibrary.dll
  5. 使用regasm注册COM程序集:
  6. regasm CSDemoLibrary.dll

注意:要从GAC中移除.NET程序集,可以使用命令:

gacutil -u CSDemoLibrary

要注销.NET程序集,可以使用命令:

regasm -u CSDemoLibrary.dll

原生(Delphi)部分

将使用Delphi2010来构建原生部分。在Delphi 2010 IDE中,创建一个新的VCL应用程序。在主表单中添加TLabel、TButton、TGauge控件。

在主表单的代码后面添加ComObj到uses部分。定义一个简单的回调过程,以更新Gauge1进度和lbMessage标题:

procedure callback(intParam: Integer; strParam: pChar); stdcall; begin Form2.Gauge1.Progress := intParam; Form2.lbMessage.Caption := strParam; Application.ProcessMessages; end;

在这个示例中,将使用后期绑定。更新btnProcess点击事件处理程序如下:

procedure TForm2.btnProcessClick(Sender: TObject); var oleObject: OleVariant; begin try oleObject := CreateOleObject('CSDemoLibrary.MyClass'); ShowMessage('result= ' + IntToStr(oleObject.Process(10, LongInt(@callback), 0, 'initialization'))); except on E: Exception do ShowMessage('COM Error: ' + #13 + #10 + e.Message); end; end;
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485