调用Delphi dll函数时的PInvokeStackImbalance

本文关键字:PInvokeStackImbalance 函数 Delphi dll 调用 | 更新日期: 2023-09-27 18:24:32

(非COM)Delphi dll有一个正在导出的函数:

function GetQuestions(Digit1, Digit2: string; CountryISO: string):string;

我已将此dll添加为Visual Studio 2012中的现有项,并将其"生成操作"设置为"无",将"复制到输出目录"设置为始终复制。

包含DllImportAttribute:的类

public class RefundLibrary
{
    [DllImport("RefundLibrary.dll", EntryPoint = "GetQuestions", 
        CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
    public static extern IntPtr GetQuestions(string digit1, string digit2, 
        string countryISO);
}

当我在WebForm的Page_Load中调用此方法时(不确定是否相关),它会在下面指示的行上抛出一个可能的签名不匹配的PInvokeStackImbalance

protected void Page_Load(object sender, EventArgs e)
{
    IntPtr str = RefundLibrary.GetQuestions("", "", "BE"); //<- here
    string result = Marshal.PtrToStringUni(str);
    testp.InnerText = result;
}

我还尝试将DllImport方法的返回类型更改为字符串,错误完全相同。

我认为就Embarcadero文档而言,Marshal.PtrToStringUni(str)是正确的?

在RAD Studio中,字符串是UnicodeString 的别名

这真的是签名不匹配吗?我缺少什么(显然,除了对P/Invoke有一个不错的理解)?

调用Delphi dll函数时的PInvokeStackImbalance

您不能调用该函数。它使用仅Delphi的register调用约定,并使用Delphi字符串。更改为:

procedure GetQuestions(
    Digit1: WideString;
    Digit2: WideString; 
    CountryISO: WideString;
    out Questions: WideString
); stdcall;

在C#侧:

[DllImport("RefundLibrary.dll")]
public static extern void GetQuestions(
    [MarshalAs(UnmanagedType.BStr)]
    string digit1,
    [MarshalAs(UnmanagedType.BStr)]
    string digit2,
    [MarshalAs(UnmanagedType.BStr)] 
    string countryISO,
    [MarshalAs(UnmanagedType.BStr)]
    out string questions
);

WideString/BStr的使用对于out参数来说是非常好的。因为内容是在共享COM堆上分配的,这意味着调用者可以解除分配。

您可以使用PWideChar/LPWStr作为输入参数。那会很好的。我使用WideString是因为我想保持一致。这取决于你。

相关文章:
  • 没有找到相关文章