我使用的是Delphi 2005(是的,它的版本相当旧,但目前我还有我必须使用的版本),我尝试使用Visual Studio 2017使用C#创建的DLL看看我是否能让它发挥作用。我的想法是,由于C#比旧的Delphi更先进,我可以在DLL中调用一些方法而不是用Delphi编程(其中一些方法已经由我们公司的其他人编程)。我的问题是我不太清楚如何做到这一点。
据我所知,可以在不注册DLL的情况下从Delphi调用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;
}
}
}
这段代码是否正确?
另一件事是,我并不完全确定我是否正确创建了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.
我将CalcTest.dll放在Delphi创建exe文件的目录中。我尝试将行开始"函数sum(..."在私有声明下,但这显然不是正确的事情。我也试图保留代码并只添加函数声明在私人声明下,但都没有奏效。
欢迎任何帮助。
答案 0 :(得分: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';
因为在编写互操作代码时匹配二进制接口非常重要,所以我倾向于不依赖于DllExport
属性的默认调用约定。我更喜欢明确:
[DllExport(CallingConvention = CallingConvention.StdCall)]
最后一个问题是你的C#方法必须声明为static
。
[DllExport(CallingConvention = CallingConvention.StdCall)]
public static int sum(int a, int b)
{
return a + b;
}