2016-08-15 13 views
-2

Я вызываю родную dll из C# Mono, и я не могу захватить исключения с предложением try catch C#. Очевидно, Mono не поддерживает это, независимо от установленных флагов (как в соответствии с другими сообщениями здесь об этой проблеме). Моно всегда будет просто закрываться, как только исключение покинет родную сторону.Захват собственного исключения из C# и получение исключения. What() после его удаления.

Решение, которое я придумал, состоит в том, чтобы передать [Out]IntPtr errorText со всеми методами exll exll из C#. Это получает родную сторону как char **. Нативная функция C++ завершает все в статье try catch(const std::exception& ex). Если нет исключения, я устанавливаю errorText в значение nullptr, но если есть исключение, я устанавливаю его в *errorText=ex.what()

Когда внутренний вызов возвращается, он либо имеет нулевой указатель на ошибку, что означает исключение, либо не равно нулю в этом случае я извлекаю его как Marshal.PtrToStringAnsi(errorText)

Это работает и не работает. Исключения попадают и указатель устанавливается, но вызов маршала возвращает null из IntPtr. После некоторого тестирования я понимаю, что если я установлю собственный указатель текста ошибки на константу, например *errorText="a test", то он будет работать по назначению.

Проблема заключается в том, что исходный объект исключения выходит за пределы области видимости, когда возвращаемая нативная функция возвращается, и в этот момент текст становится недействительным, что означает, что это неверно, когда я пытаюсь маршалировать содержимое из указателя на него.

Одним из решений являются всегда сами бросать константные строки в виде исключения, как throw "something bad" и поймать, что, поскольку эти постоянные строки остаются в силе, а затем поймать другие std::exception сек возвращающихся только родовое строку ошибки, как «неопределенного станд :: исключение».

Это, очевидно, не идеально, хотя оно может работать. Вопрос в том, почему именно я не могу добраться до *what() после выхода из функции. Хотя фактический объект исключения может выйти из области видимости, сообщение, которое оно было создано, обычно является константой. Если я сделаю бросок std::exception("something"), тогда what должен указывать на константу «что-то» и должен оставаться в силе после того, как исключение выходит за рамки.

Я рассмотрел вопрос о создании массива постоянных символов в dll и скопировал его() в него для последующего извлечения, но мне нужно поддерживать несколько одновременных доступов, которые могут иметь несколько исключений одновременно, над этим буфером.

Мне очень интересно, есть ли у кого-нибудь представление о том, почему what() недоступен после того, как исключение оставляет видимость области или хорошая идея для решения этого более элегантно, чем путем исключения строковых исключений.

Редактировать: Еще одно решение состоит в том, чтобы выделить строку для управляемой стороны сообщения об ошибке и передать указатель на это для собственной стороны, чтобы вставить ошибку. Мне просто не нужно выделять новую строку для каждого вызова ... хотелось бы просто получить указатель на фактическое сообщение в том, что()

+0

Возможно, релевантно. (http://stackoverflow.com/questions/150544/can-you-catch-a-native-exception-in-c-sharp-code) –

+0

Возможно, решение: (http: // stackoverflow.com/questions/6850091/how-to-catch-unmanaged-c-exception-in-managed-c) –

+0

Это, безусловно, похоже, но я не могу исключить исключение из моего собственного кода, как в ссылке. Это вызывает мгновенное завершение, и я также не могу выделить мусор, собранный для сообщения из собственного кода ... который является чистым C++ без добавления ms. Играй мне идею, тем не менее, поэтому я продлю свое сообщение – JoeTaicoon

ответ

2

Вы можете выделить char-buffer (внутри родной DLL) для своего " errorText "-параметр и скопировать текст" ex.what() "в этот буфер. В этом случае память останется действительной. Но я думаю, вам придется освободить char-buffer самостоятельно после того, как вы прочитаете строку на C#, чтобы предотвратить утечку памяти.

+0

Спасибо, но я уже рассмотрел и отклонил это, согласно моему вопросу. – JoeTaicoon

+0

Я был немного несправедлив к вашему ответу, потому что вы на самом деле не сказали, что буфер должен быть разделен между всеми вызовами. Решение, которое я использую сейчас, состоит в том, чтобы выделить буфер для исключения и передать указатель обратно в управляемый. Затем управляемый задается вызовом собственного удаления по этому указателю после чтения текста. Поэтому я, очевидно, должен принять ваш ответ. Извините, если я неправильно вас понял. – JoeTaicoon