如何在Delphi中使用用C#创建的DLL

jon*_*imv 1 c# delphi dllimport

我使用的是Delphi 2005(是的,它是相当旧的版本,但目前我就是我必须使用的)并且我尝试使用Visual Studio 2017使用C#创建的DLL来查看我是否可以使它工作.我的想法是,由于C#比旧的Delphi更先进,我可以在DLL中调用一些方法而不是用Delphi编程(其中一些方法已经由我们公司的其他人编程).我的问题是我不太清楚如何做到这一点.

我已经知道可以从Delphi调用DLL而无需注册DLL.这实际上或多或少是游戏破坏者,如果没有注册它就没有实际的方法来使用DLL,因为它使我们的软件更复杂,现在它的工作方式.

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

using RGiesecke.DllExport;
using System;

namespace CalcTest
{
    public class CalcTest
    {
        [DllExport]
        public int sum(int a, int b)
        {
            return a + b;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这段代码是否正确?

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

应用程序无法正确启动(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.
Run Code Online (Sandbox Code Playgroud)

我在与Delphi创建exe文件的目录相同的目录中有CalcTest.dll.我试图在"私人声明"下面开始"功能总和(..."这一行,但这显然不是正确的事情.我也试图保留代码,只是在私人声明下添加功能声明但是没有工作.

欢迎任何帮助.

Dav*_*nan 5

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

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

function sum(a, b: integer): integer; stdcall; external 'CalcTest.dll';
Run Code Online (Sandbox Code Playgroud)

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

[DllExport(CallingConvention = CallingConvention.StdCall)]
Run Code Online (Sandbox Code Playgroud)

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

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

  • 查看我回滚的最新编辑,您实际上现在有一个完全不同的错误条件.所以当你说"同样的问题"时,这与你发布的内容相矛盾.您现在可以设法开始执行该应用程序.这意味着您提出的问题已得到解答,您现在遇到了新问题.这里的问题不适用于扩展调试会话,您需要让我们调试整个程序,从一个bug到下一个bug,直到它们全部消失.你问了一个问题,它得到了答案.而已. (4认同)