我最近遇到的问题如下。
我有一个用Delphi编写的.DLL,该DLL具有功能Divide(该函数接受两个整数作为参数)并按原样返回其值。
function Divide( aFirstValue, aSecondValue : Integer ) : Double; stdcall;
begin
result := aFirstValue / aSecondValue;
end;
现在,如果我使用以下参数“ 5、0”,那么它将引发DivideByZeroException(这是正确的:))
但是,当我从C#调用相同的.DLL时,它根本不会捕获任何异常。
[DllImport("DelphiDLL.DLL", EntryPoint = "Divide", SetLastError = true, CharSet = CharSet.Auto, ExactSpelling = true,
CallingConvention = CallingConvention.StdCall)]
public static extern float Divide(Int32 a, Int32 b);
private void Button_Click_2(object sender, System.EventArgs e)
{
try
{
TB.Text += "Divide(a,b) = ";
float temp;
temp = Divide(Convert.ToInt32(aTB.Text), Convert.ToInt32(bTB.Text));
Console.WriteLine(Marshal.GetLastWin32Error());
TB.Text += Convert.ToString(temp) + "\r\n";
}
catch (DivideByZeroException eMsg)
{
}
}
您不能希望在DLL之外捕获该异常。这种二进制互操作形式的规则之一是,不能跨模块边界引发异常。
解决方法是修复DLL。在DLL中捕获异常并返回错误代码以指示失败。实际上,您应该保护所有入口点,以免引发异常。不要只捕获零除异常,捕获所有异常并将它们转换为错误代码返回值。
function CalcQuotient(a, b: Integer; out quotient: Double): Integer; stdcall;
begin
try
quotient := a / b;
Result := 0;// you'd use a constant with a sensible name rather than a magic value
except
on E: Exception do begin
Result := GetErrorCode(E);
// where GetErrorCode is your function that converts exceptions into error codes
end;
end;
end;
有关p / invoke用法的一些帮助:
CharSet
何时所有参数都不包含文本。SetLastError = true
不正确,应将其删除。该函数不会调用SetLastError
。因此,对的调用Marshal.GetLastWin32Error()
是错误的,应删除。本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句