调用Delphi dll函数时的PInvokeStackImbalance

时间:2014-09-25 13:44:58

标签: c# delphi pinvoke dllimport delphi-xe5

一个(非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方法的返回类型更改为字符串,错误相同。

我认为Marshal.PtrToStringUni(str)对于Embarcadero docs来说是正确的吗?

  

在RAD Studio中,string是UnicodeString的别名

这真的是签名不匹配吗?我错过了什么(显然,除了对P / Invoke的理解之外)?

1 个答案:

答案 0 :(得分:3)

您无法调用该功能。它使用仅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因为我想保持一致。它取决于你。