创建C#DLL并从Delphi调用 [英] Create C# DLL and Call from Delphi

查看:0
本文介绍了创建C#DLL并从Delphi调用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用Delphi的第三方DotNet库(只有几个函数),并计划创建一个C#DLL作为接口。我用C#(VS 2019/.NET5)创建了一个简单的演示DLL作为测试,其中包含一个返回整数的函数(稍后,我想添加一个返回字符串的函数)。从Delphi 10.4调用DLL时,我收到以下错误:

在动态链接库D:源CodeDelphiTestDLLCSharpWin64DebugTestDLLProject.exe

中找不到过程入口点Add

我正在使用this technique创建DLL。

我的C#代码在类库中:

using System;
using System.Runtime.InteropServices;

namespace TestDLLForDelphiV2
{
    [ComVisible(true)]
    [Guid("8F8F51AA-1A66-4689-83EF-CF61ED99EA92")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

    public interface ICalc
    {
        int Add();
    }

    [ComVisible(true)]
    [Guid("BEB943AE-A406-4F55-A9E5-DD3B12F8D17B")]
    public class Calc : ICalc
    {
        private int numberOne = 3;
        private int numberTwo = 5;

        // Add two integers
        [ComVisible(true)]
        public int Add()
        {
            return numberOne + numberTwo;
        }         
    }
}

Visual Studio项目文件:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>net5.0</TargetFramework>
    <Platforms>x64</Platforms>
    <EnableComHosting>true</EnableComHosting>
    <EnableRegFreeCom>true</EnableRegFreeCom>
    <GeneratePackageOnBuild>false</GeneratePackageOnBuild>
  </PropertyGroup>

  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
    <PlatformTarget>x64</PlatformTarget>
    <EnableComHosting>true</EnableComHosting>
    <EnableRegFreeCom>true</EnableRegFreeCom>
  </PropertyGroup>

</Project>

调用DLL的Delphi代码:

unit Main;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants,
  System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  ShellApi;

function Add: Integer; stdcall; // cdecl;  NOTE - I tried with both stdcall and cdecl
External 'TestDLLForDelphiV2.comhost.dll';  //NOTE - Also attempted with TestDLLForDelphiV2.dll

procedure TForm1.Button1Click(Sender: TObject);
var
  i: Integer;
begin
  Memo.Clear;

  i := Add;
  Memo.Lines.Add(IntToStr(i));

end;

end.

DLL是用.NET5创建的,我知道regasm.exe不支持.NET5,这与以前的.NET版本不同。根据上面的文章,我已经使用regsvr32.exe注册了DLL,并尝试了REG Free COM选项(使用项目文件中的EnableRegFreeCom标记)。DLL和Delphi应用程序都编译为64位。如有任何提示、建设性的帮助等,我们将不胜感激。

推荐答案

使用C++加载.NET框架并在其中创建C#对象

gcroot<Calc^> calc = nullptr;

bool __stdcall GetCalc(int& obj)
{
  using namespace System::Runtime::InteropServices;
  if (calc.operator->() == nullptr)
    calc= gcnew Calc();
  System::IntPtr p = Marshal::GetIUnknownForObject(calc);

  void* q = p.ToPointer();
  obj= (int)q;
  return true;

}

Delphi:

type
  ICalc=interface(IInterface)
  ['{8F8F51AA-1A66-4689-83EF-CF61ED99EA92}']
    function Add: integer; safecall;
end;

procedure test;
type
  TFunc=function(var ASrv: IInterface): boolean; stdcall;
var
  Lhn    : THandle;
  Lfunc  : TFunc;
  Lif    : IInterface;
  LifCalc: ICalc;
begin
  Lhnd  := LoadLibrary(<C++ DllName>);
  try
    Lfunc := GetProcAdress(Lhnd, 'GetCalc');
    
    Lfunc(Lif);
    if Supports(Lif, ICalc, LifCalc) then
      ShowMessage(LifCalc.Add.ToString)
   else
      raise Exception.Create('Error');
 
 finally
   FreeLibrary(Lhnd);
 end;
end;

C#

namespace TestDLLForDelphiV2
{
[ComVisible(true)]
[Guid("8F8F51AA-1A66-4689-83EF-CF61ED99EA92")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]

public interface ICalc
{
    [return: MarshalAs(UnmanagedType.I4)]
    int Add();
}

public class Calc : ICalc
{
    private int numberOne = 3;
    private int numberTwo = 5;

    // Add two integers
    public int Add()
    {
        return numberOne + numberTwo;
    }         
}
}

这篇关于创建C#DLL并从Delphi调用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆