c++ - 在 .NET 中捕获非托管 dll 异常

标签 c++ .net vb.net winapi dll

我正在使用一个带有抛出 std::exception 函数的非托管 DLL。

我正在使用 .NET DLL 包装器,因此可以分发它以在 .NET 程序中使用。

我希望能够从 native 异常中捕获消息,但我得到的只是 System.Runtime.InteropServices.SEHException("External component has thrown an exception.")

有什么方法可以传播异常详细信息吗?也许我应该从 native DLL 导出自定义异常?我该怎么做?

谢谢

native DLL:

__declspec(dllexport) void __stdcall W32DLLFunc(int param) {
  if (param < 0) {
    throw new exception("Error: param must be > 0");
  }
  ...
}

.net 动态链接库:

[DllImport("nw32.dll", CharSet = CharSet::Auto)]
static void W32DLLFunc(int param);

vb.net 程序:

Try
  W32DLLFunc(-1)
Catch ex As Exception
  MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try

最佳答案

native C++ 异常是 native C++ 异常。它们不适用于非 C++ 的东西。它们甚至不能在不同版本的 C++ 之间工作。

native C++ 异常不利于互操作性。

从 DLL 返回错误信息的标准机制是返回一个值来指示成功或失败并使用 SetLastErrorGetLastError如果函数失败,则传达错误代码。

如果您希望标准机制返回比错误代码更多的信息,您需要查看 COM,它有 IErrorInfo .

但是定义一些错误代码会更简单。

如果可能,我会更改原始 DLL,使其完全不会泄漏异常。如果这是不可能的,因为现有的 C++ 客户端依赖于当前的设计,那么我将添加一个并行 API:调用原始函数的每个导出函数的新版本,捕获异常并返回错误代码。这是所有可以隐藏在宏中的样板。如果您不能接触 DLL,我会添加一个本地包装器来转换异常。

更新

根据 IInspectable 的建议,另一种选择是创建混合模式程序集。

将 .Net 类添加到您现有的 C++ 库中。这应该为调用原始 API 的每个 API 函数提供一个包装器,捕获任何异常,将详细信息复制到 .Net 异常并抛出 .Net 异常。

通过将所有 native 异常处理保留在 DLL 中,这避免了 C++ 异常跨越 DLL 边界的问题。包装的异常可以在任何 .Net 语言中使用,而无需为导出的函数创建声明。唯一的缺点是您需要额外的 API 才能与其他 native 代码进行互操作。

关于c++ - 在 .NET 中捕获非托管 dll 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20610480/

相关文章:

c# - .NET 实例方法中的 this == null - 为什么这可能?

c# - 何时使用多个类库?

.net - 这个 Wix 声明在做什么?

javascript - 回发时 HTML 输入值清除

jquery - jquery中如何获取某个字符的lastindex?

c# - 从 Access 数据库收集数据

c++ - 无法用 64 位 g++ 编译 32 位

c++ - 我如何使用 std::shared_ptr 和 box2d?

c++ - 如何在 symbian S60 Qt 应用程序中启动浏览器并加载 url?

c++ - 为什么 uint32_t 与 uint64_t 速度差异?