【问题标题】:Can't handle exceptions when invoking C# function from unmanaged C++ code从非托管 C++ 代码调用 C# 函数时无法处理异常
【发布时间】:2021-08-27 16:25:20
【问题描述】:

问题的想法如下:我将 C# 函数指针传递给 C++ 编译库,然后从 C++ 调用传递函数。我想从代码中捕获 C#/C++ 异常,该异常位于 before C++ 函数调用。

问题的想法如下:我将 C# 函数指针传递给 C++ 编译库,然后从 C++ 调用传递函数。我的 C++ 调用包含在 try/catch 中,我想从 C++/C# 函数中捕获异常。

所以,我有 .NET 5 应用程序,它运行以下代码:

class NetProgram
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate void CustomCppFunc(int id);

    [DllImport("/root/projects/LinuxLoop/bin/x64/Debug/libLinuxLoop.so")]
    protected static extern void strg_Create(IntPtr cb_is_my);

    static void Main(string[] args)
    {
        CustomCppFunc sharpDelegate = new CustomCppFunc(Smth.sharpStaticMethod);

        try
        {
            strg_Create(Marshal.GetFunctionPointerForDelegate(sharpDelegate));
        }
        catch (Exception e)
        {
            Console.WriteLine("Catched exception from C# Program: " + e.Message);
        }
        finally
        {
            Console.WriteLine("Finally from C# Program.");
        }
    }

    public class Smth
    {
        public static void sharpStaticMethod(IntPtr id)
        {
            Console.WriteLine("C#. sharpStaticMethod. Invoked.");

            Console.WriteLine("C#. sharpStaticMethod. Zero division.");
            var b = 0;
            var a = 1 / b;
        }
    }

}

libLinuxLoop.so 是 C++ 编译的 Linux 库(我使用的是 CentOS 7),它有以下内容:

MyCppFunc.h:

#ifdef MYCPPFUNC
#define MYCPPFUNC __attribute__((dllexport))
#else
#define MYCPPFUNC __attribute__((dllimport))
#endif

typedef void(*CBIsMy)(int order_id);

extern "C" MYCPPFUNC void *strg_Create(CBIsMy cb_is_my);

MyCppFunc.cpp:

#include <cstdio>
#include <utility>
#include <limits.h>
#include "MyCppFunc.h"

void *strg_Create(CBIsMy cb_is_my) {
    std::fputs("C++. strg_Create. Invoked.\n", stdout);

    std::fputs("C++. strg_Create. Invoking C# delegate.\n", stdout);
    cb_is_my(1);

    return NULL;
}

正在运行的应用程序会写入以下消息:

C++. strg_Create. Invoked.
C++. strg_Create. Invoking C# delegate.
C#. sharpStaticMethod. Invoked.
C#. sharpStaticMethod. Zero division.
Unhandled exception. System.DivideByZeroException: Attempted to divide by zero.
at TestPlayground0806.NetProgram.Smth.sharpStaticMethod(Int32 id) in C:\Users\dev02\source\repos\TestPlayground0806\TestPlayground0806\NetProgram.cs:line 106
Aborted (core dumped)

结果:由非托管代码调用的 C# 函数引发异常会使整个应用程序崩溃。为了捕获这些异常,我应该怎么做?

UPD: 异常在 Windows 10 上被捕获,但我无法在 CentOS 7 上捕获。

【问题讨论】:

  • C# 例程应该捕获异常,而不是将其传递给非托管代码。
  • @Eljay,感谢您的回复。在 Windows 10 上可以捕获 C# 异常,但在 CentOS 7 上,异常只会使整个应用程序崩溃。
  • 如果sharpStaticMethod 捕获异常会怎样?
  • 在上面的示例中,我制作了 1/0,它提供了“DivideByZeroException”。在 CentOS 7 上,它会抛出一个异常,该异常不会被 Main 中的 try/catch 部分捕获。然后整个应用程序崩溃。
  • 更改示例以让sharpStaticMethod 捕获异常。

标签: c# c++ .net linux dllexport


【解决方案1】:

它在 Windows 上以这种方式工作,因为 Windows 堆栈帧通过非托管帧支持异常机制。它在 Linux 上不起作用,因为 Linux 堆栈帧不支持通过非托管帧的异常机制。 – 艾尔杰

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多