创建C#DLL并从Delphi调用 [英] Create C# DLL and Call from Delphi
本文介绍了创建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屋!
查看全文