PInvokeStackImbalance when calling Delphi dll function

匆匆过客 提交于 2019-12-11 03:59:31

问题


A (non-COM) Delphi dll has a function being exported:

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

I have added this dll as an existing item in Visual Studio 2012 and have set its Build Action to None, Copy to Output Directory to Copy Always.

The class containing the 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);
}

When I call this method in the Page_Load of a WebForm (not sure if relevant), it throws a PInvokeStackImbalance for a possible signature mismatch on the below indicated line:

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

    testp.InnerText = result;
}

I also tried to change the DllImport method's return type to string, the error is identical.

I figure the Marshal.PtrToStringUni(str) is correct as far as the Embarcadero docs go?

In RAD Studio, string is an alias for UnicodeString

Is this really a signature mismatch? What am I missing (except, obviously, a decent understanding of P/Invoke)?


回答1:


You cannot call that function. It uses the Delphi only register calling convention, and uses Delphi strings. Change it to:

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

On the C# side:

[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
);

The use of WideString/BStr is great for the out parameter. Because the content is allocated on the shared COM heap which means that the caller can deallocate it.

You could use PWideChar/LPWStr for the input parameters. That would work fine. I used WideString because I wanted to be consistent. It's up to you.



来源:https://stackoverflow.com/questions/26040211/pinvokestackimbalance-when-calling-delphi-dll-function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!