문제

I would like to make my extern C++ function return a message when an exception occurs. Something like this:

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);
}

On the other hand, I call the function from my C# program and I would like to show error in 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);
    ...
}

Unfortunately, it doesn't work.. the MessageBox just shows random characters.

I'm surprised because if I replace:

return e.what();

by:

const char* err = "parameters error!";
return err;

Then "parameters error!" will be shown correctly in the messagebox of the C# code. Both err and e.what() are the same type (const char*), so what's wrong with e.what()??

도움이 되었습니까?

해결책 2

Have your function return a BOOL instead, with the error message string as a parameter, like:

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;
}

and invoke it like

StringBuilder sErr = new StringBuilder(256);
if (!Calculate(out result, 2, 3, sErr, 256))
    MessageBox.Show(sErr);

다른 팁

When you are using a string literal as a return value from a function, it will work properly. But same is not the case with local variable e. You need to create a dynamic char* to store the value of e.what() in that and return that value.

It's because the exception string is pointing to a string which destroyed once the exception handler is done. You might need to return e.g. std::string and marshal that into a C# string.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top