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# プログラムから関数を呼び出して、エラーを表示したい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

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

これは、例外文字列が、例外ハンドラが完了すると破棄される文字列を指しているためです。std::stringeg を返し、それを C# にマーシャリングする必要がある場合がありますstring

于 2013-08-10T14:02:36.983 に答える