问题
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