一个(非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的理解之外)?
答案 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
因为我想保持一致。它取决于你。