如何在Delphi中使用C#创建的DLL [英] How to use a DLL created with C# in Delphi

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

问题描述

我使用的是Delphi 2005(是的,它是一个很旧的版本,但现在我必须使用它),并且我尝试使用通过Visual Studio 2017 C#创建的DLL,以查看是否可以使它工作。想法是,由于C#比这个旧的Delphi先进得多,因此我可以在DLL中调用某些方法,而不是使用Delphi进行编程(这些方法中的某些已经由我们公司的其他人员进行了编程)。我的问题是我不太确定如何做到这一点。

I use Delphi 2005 (yes, it's pretty old version but at the moment I that's what I have to use) and I have tried to use a DLL created with C# using Visual Studio 2017 to see if I can make it work. The idea is that as C# is much more advanced than this old Delphi I could call some methods in the DLL instead of programming those with Delphi (some of those methods are already programmed by some other people in our company). My problem is that I am not quite sure how to do this.

我了解可以在不注册DLL的情况下从Delphi调用DLL。如果没有未经注册就没有使用DLL的实际方法,这实际上或多或少是破坏者,因为与我们现在的工作方式相比,它使交付我们的软件更加复杂。

I have understood that it is possible to call a DLL from Delphi without registering the DLL. This is actually more or less gamebreaker if there is no actual way to use a DLL without registering it because it makes delivering our software a bit more complicated that how it works now.

首先,我想知道是否正确创建了PoC DLL。我创建了一个新项目(类库)并针对x86进行了编译,因为使用Delphi 2005创建的程序是32位程序,这是此非常简单的DLL的代码。

First I would like to know if I have created the PoC DLL correctly. I made a new project (Class Library) and compiled it for x86 since the programs created with Delphi 2005 are 32-bit programs and here's the code for this very simple DLL.

using RGiesecke.DllExport;
using System;

namespace CalcTest
{
    public class CalcTest
    {
        [DllExport]
        public int sum(int a, int b)
        {
            return a + b;
        }
    }
}

此代码正确吗?

另一件事是,我不确定我是否正确创建了Delphi项目。我可以构建它而没有错误,但是当我尝试运行它时,会收到错误消息:

Another thing is that I am not entirely certain that I have created the Delphi project correctly. I can build it without errors but when I try to run it I get an error message:

该应用程序无法正确启动(0xc000007b)。单击确定关闭该应用程序。

这里是代码。

unit TestForm_u;

interface

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

type
  TTestForm = class(TForm)
    Button1: TButton;
    summa_lb: TLabel;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    procedure Laske;
  public
    { Public declarations }
  end;

var
  TestForm: TTestForm;

implementation

{$R *.dfm}

function sum(a, b: integer): integer; external 'CalcTest.dll';

procedure TTestForm.Button1Click(Sender: TObject);
begin
  Laske;
end;

procedure TTestForm.Laske;
var
  x,y,z: integer;
begin
  x := 1;
  y := 2;
  //z := x + y;
  z := sum(x, y);

  summa_lb.Caption := IntToStr(z);
end;

end.

我在CalcTest.dll与Delphi创建exe文件的目录相同。我试图将以 function sum(...开头的行放在私有声明下,但这显然不是正确的事情。我也试图将代码保持原样,只是在私有声明下添加函数声明,但均无济于事

I have the CalcTest.dll in the same directory as where Delphi creates the exe file. I tried to place the line starting "function sum(..." under private declaration but that was clearly not a right thing to do. I have also tried to leave the code as is and just add function declaration under private declaration but neither worked.

欢迎任何帮助。

推荐答案

错误代码是 NTSTATUS 代码 STATUS_INVALID_IMAGE_FORMAT 。通常是64位进程尝试(失败)加载32位DLL,反之亦然。您需要确保所有模块的位数匹配。由于您的Delphi编译器只能生成32位可执行文件,因此您的C#项目必须以x86为目标。

The error code is the NTSTATUS code STATUS_INVALID_IMAGE_FORMAT. That is typically a 64 bit process trying (and failing) to load a 32 bit DLL, or vice versa. You need to make sure that the bitness of all modules matches. Since your Delphi compiler can only produce 32 bit executables, your C# project must target x86.

下一个问题是调用约定之一,您的C#导出使用 stdcall ,但是您的Delphi导入未指定调用约定,因此默认使用 register 。将Delphi更改为:

The next problem is one of calling conventions. Your C# export uses stdcall, but your Delphi import does not specify a calling convention and so you defaults to register. Change the Delphi to:

function sum(a, b: integer): integer; stdcall; external 'CalcTest.dll';

因为在编写互操作代码时匹配二进制接口非常重要,所以我倾向于依赖 DllExport 属性的默认调用约定。我宁愿明确一点:

Because it is so important to match the binary interfaces when writing interop code, my inclination would be not to rely on the default calling convention of the DllExport attribute. I'd prefer to be explicit:

[DllExport(CallingConvention = CallingConvention.StdCall)]

最后一个问题是您的C#方法必须声明为 static

And the final problem is that your C# method must be declared static.

[DllExport(CallingConvention = CallingConvention.StdCall)]
public static int sum(int a, int b)
{
    return a + b;
}

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

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