C# P/Invoked 来自 BPL 的函数 returns 指向 Delphi 记录的相同指针,无论输入如何

C# P/Invoked function from BPL returns same pointer to Delphi record regardless of input

我正在尝试使用来自国外 BPL 包的函数,但我无权访问其代码。

虽然我在 Delphi 中取得了成功,但在 C# 中我仍然得到相同的值,无论输入如何。

BPL 在 Delphi

中的外部使用
type
  PRecord = ^TRecord;
  TRecord = packed record
      S: string;
      LW: LongWord;
  end;    

function GetValue(W : Word) : PRecord; external 'package.bpl' name '@Unit@Function$qqrus';

调用 GetValue() 不同的输入 returns 不同的记录,这是正确的。

BPL 在 C# 中的外部使用

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct TRecord
{
    public string S;
    public int LW;
}
        
[DllImport("package.bpl", EntryPoint = "@Unit@Function$qqrus", CharSet = CharSet.Unicode)]
static extern IntPtr GetValue(ushort number);
    
public static TRecord GetDelphiValue(ushort number)
{
    var ptr = GetValue(number);
    return (TRecord) Marshal.PtrToStructure(ptr, typeof(TRecord))
}

使用不同的输入调用 GetDelphiValue() 总是 returns 相同的指针和结构。

我错过了什么?

function GetValue(W : Word) : PRecord; 
  external 'package.bpl' name '@Unit@Function$qqrus';

此函数使用Delphi的默认调用约定,即register。其他工具不支持此功能,因此无法从您的 C# 代码调用此函数。

您需要在 C# 代码和 Delphi 程序包之间放置一个 Delphi DLL。 Delphi DLL 将能够调用 register 调用约定函数,并且可以导出具有 stdcall 调用约定的函数供您的 C# 代码调用。

此外,您还有机会解决因使用 Delphi string 类型而引起的任何潜在问题,该类型也是 Delphi.[=17 私有的=]

就其价值而言,我非常怀疑该函数是否确实 return 指向记录的指针。我认为这更有可能是一个将记录作为 varout 参数的过程。而且我确实认为很可能存在与该字符串的生命周期相关的问题。实际上,您不能指望使用没有关于其接口信息的二进制模块。