我想让我的extern C ++函数在发生异常时返回一条消息。像这样:
extern "C" __declspec(dllexport) const char* __stdcall Calculate(double &result, double a, double b)
{
try
{
result = InternalCalculation(a, b);
}
catch(std::invalid_argument& e)
{
return e.what();
}
return "";
}
double InternalCalculation(double a, double b)
{
if(a < b)
{
const char* err = "parameters error!";
throw std::invalid_argument(err);
}
return sqrt(a - b);
}
另一方面,我从我的C#程序调用该函数,我想在MessageBox
中显示错误:
[DllImport(@"MyDll.dll", EntryPoint = "Calculate")]
private static extern IntPtr Calculate(out double result, double a, double b);
private void Calculate()
{
IntPtr err;
double result = 0;
err = Calculate(out result, out 2, out 3);
var sErr = Marshal.PtrToStringAnsi(err);
if (string.IsNullOrEmpty(sErr))
MessageBox.Show(sErr);
...
}
不幸的是,它不起作用.. MessageBox
只显示随机字符。
我很惊讶,因为如果我更换:
return e.what();
由:
const char* err = "parameters error!";
return err;
然后“参数错误!”将在C#代码的消息框中正确显示。 err
和e.what()
都是相同的类型(const char*
),所以e.what()
的错误是什么?
答案 0 :(得分:2)
当您使用字符串文字作为函数的返回值时,它将正常工作。但局部变量e的情况并非如此。您需要创建一个动态char*
来存储e.what()
的值并返回该值。
答案 1 :(得分:1)
让您的函数返回BOOL
,并将错误消息字符串作为参数,例如:
BOOL Calculate(double &result, double a, double b, char *pMsg, size_t nMsgSize)
{ try
{ result = InternalCalculation(a, b);
}
catch(std::invalid_argument& e)
{ strncpy_s(pMsg, nMsgSize, e.what(), _TRUNCATE);
return FALSE;
}
return TRUE;
}
并像
一样调用它StringBuilder sErr = new StringBuilder(256);
if (!Calculate(out result, 2, 3, sErr, 256))
MessageBox.Show(sErr);
答案 2 :(得分:0)
这是因为异常字符串指向一个在异常处理程序完成后销毁的字符串。您可能需要返回,例如std::string
并将其编组为C#string
。