3

我想让我的 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# 程序中调用该函数,我想在 a 中显示错误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()??

4

3 回答 3

2

当您使用字符串文字作为函数的返回值时,它将正常工作。但局部变量 e 的情况并非如此。您需要创建一个动态char*来存储其中的值e.what()并返回该值。

于 2013-08-10T14:08:10.757 回答
1

让您的函数返回 a 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);
于 2013-08-10T16:59:43.107 回答
0

这是因为异常字符串指向一个字符串,一旦异常处理程序完成,该字符串就会被销毁。您可能需要返回 egstd::string并将其编组为 C# string

于 2013-08-10T14:02:36.983 回答