NativeAOT提供了一个示例c#类,其中的方法标记为“UnmanagedCallersOnly”,我理解它是打算在非托管语言(如 Delphi )中使用的。提供的示例类是:
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System;
using System.Runtime.InteropServices;
namespace NativeLibrary
{
public class Class1
{
[UnmanagedCallersOnly(EntryPoint = "add")]
public static int Add(int a, int b)
{
return a + b;
}
[UnmanagedCallersOnly(EntryPoint = "write_line")]
public static int WriteLine(IntPtr pString)
{
// The marshalling code is typically auto-generated by a custom tool in larger projects.
try
{
// UnmanagedCallersOnly methods only accept primitive arguments. The primitive arguments
// have to be marshalled manually if necessary.
string str = Marshal.PtrToStringAnsi(pString);
Console.WriteLine(str);
}
catch
{
// Exceptions escaping out of UnmanagedCallersOnly methods are treated as unhandled exceptions.
// The errors have to be marshalled manually if necessary.
return -1;
}
return 0;
}
[UnmanagedCallersOnly(EntryPoint = "sumstring")]
public static IntPtr sumstring(IntPtr first, IntPtr second)
{
// Parse strings from the passed pointers
string my1String = Marshal.PtrToStringAnsi(first);
string my2String = Marshal.PtrToStringAnsi(second);
// Concatenate strings
string sum = my1String + my2String;
// Assign pointer of the concatenated string to sumPointer
IntPtr sumPointer = Marshal.StringToHGlobalAnsi(sum);
// Return pointer
return sumPointer;
}
}
}
(from:Class1.cs)
如何从 Delphi 调用方法(Add、WriteLine和sumstring)?
编辑2023年1月1日
我已经浏览了链接(也尝试了ChatGPT),但我仍然没有让它工作。我有一个从C#代码编译的NativeLibrary.DLL文件。使用dotPeek,我可以看到Add函数在DLL中。我使用的项目文件是:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>net7.0</TargetFramework>
<PublishSingleFile>true</PublishSingleFile>
<SelfContained>true</SelfContained>
<PublishTrimmed>true</PublishTrimmed>
<PublishReadyToRun>true</PublishReadyToRun>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<Platforms>x64</Platforms>
</PropertyGroup>
</Project>
我试过用两种不同的方法从 Delphi 调用Add函数。
方法1
unit TestClass;
interface
uses
System.SysUtils,
System.Classes, Windows;
const
MY_DLL = 'NativeLibrary.dll';
type
TAddFunc = function(a: Integer; b: Integer): Integer; stdcall;
TTestClass = class
public
class function TestAdd(a: Integer; b: Integer): Integer; static;
end;
implementation
class function TTestClass.TestAdd(a: Integer; b: Integer): Integer;
var
Handle: HMODULE; // THandle
Func: TAddFunc;
begin
Handle := LoadLibrary(MY_DLL);
try
Func := GetProcAddress(Handle, 'Add');
if Assigned(Func) then
begin
Result := Func(a, b);
end;
finally
FreeLibrary(Handle);
end;
end;
end.
调用此函数的方式为:
procedure TMainForm.Button1Click(Sender: TObject);
var
StringFromDLL: string;
begin
StringFromDLL := TTestClass.TestAdd(4,10);
ShowMessage(StringFromDLL);
end;
应用程序运行,但是当调用TestAdd时,返回一个Handle,但是Func为nil,并且从未被赋值。
方法2
unit TestClass2;
interface
uses
System.SysUtils,
System.Classes, Windows;
const
MY_DLL = 'NativeLibrary.dll';
function Add(a: Integer; b: Integer): Integer; stdcall;
external MY_DLL name 'Add';
type
TTestClass2 = class
public
class function TestAdd(a: Integer; b: Integer): Integer; static;
end;
implementation
class function TTestClass2.TestAdd(a: Integer; b: Integer): Integer;
begin
Result:=Add(a,b);
end;
end.
当我使用这种技术调用TestClass2.TestAdd时,在应用程序启动时,我会得到一个提示阅读“应用程序错误-应用程序无法正确启动(0xc 000007 b)。单击OK关闭应用程序。”
1条答案
按热度按时间jpfvwuh41#
在拉撒路2.2.4(FPC 3.2.2)x86_64-win 64上进行测试
result
在Lazarus 2.2.0 FPC 3.2.2 i386-win32上,未加载“本机库. dll”(32位“测试应用程序”和64位“本机库. dll”不兼容)