Catching custom c++ exception from c# with swig

310 Views Asked by At

I'm trying to catch and wrap a custom c++ exception in c#.

Let's say I have the following exception c++ custom exception:

//custom_exception.h
namespace ns
{
    namespace exception
    {
        class CustomException
        {
        public:
            CustomException(const char* msg, EStatus status) :
                m_status(status) 
            {
                strcpy(m_msg, msg);
            }

            const char* what() const { return m_msg; }
            
            EStatus status() const { return m_status; };
        
        private:

            EStatus m_status;
            const size_t m_max_len = 100;
            char m_msg[100];
        };
    }
}

I've created the following interface file custom_exception.i according to the SWIG doc (16.3.4 Custom C# ApplicationException example):

/************************/
/***** Main Module ******/
/************************/
%module custom_exception

%{
    #include "custom_exception.h"
%}

%insert(runtime) %{
  // Code to handle throwing of C# CustomApplicationException from C/C++ code.
  // The equivalent delegate to the callback, CSharpExceptionCallback_t, is CustomExceptionDelegate
  // and the equivalent customExceptionCallback instance is customDelegate
  typedef void (SWIGSTDCALL* CSharpExceptionCallback_t)(const char *, int);
  CSharpExceptionCallback_t customExceptionCallback = NULL;

  extern "C" SWIGEXPORT
  void SWIGSTDCALL CustomExceptionRegisterCallback(CSharpExceptionCallback_t customCallback) {
    customExceptionCallback = customCallback;
  }

  // Note that SWIG detects any method calls named starting with
  // SWIG_CSharpSetPendingException for warning 845
  static void SWIG_CSharpSetPendingExceptionCustom(const char *msg, int status) {
    customExceptionCallback(msg, status);
  }
%}

%pragma(csharp) imclasscode=%{
  class CustomExceptionHelper {
    // C# delegate for the C/C++ customExceptionCallback
    public delegate void CustomExceptionDelegate(string message, int status);
    static CustomExceptionDelegate customDelegate =
                                   new CustomExceptionDelegate(SetPendingCustomException);

    [global::System.Runtime.InteropServices.DllImport("$dllimport", EntryPoint="CustomExceptionRegisterCallback")]
    public static extern
           void CustomExceptionRegisterCallback(CustomExceptionDelegate customCallback);

    static void SetPendingCustomException(string message, int status) {
      SWIGPendingException.Set(new CustomException(message, status));
    }

    static CustomExceptionHelper() {
      CustomExceptionRegisterCallback(customDelegate);
    }
  }
  static CustomExceptionHelper exceptionHelper = new CustomExceptionHelper();


%}

%pragma(csharp) moduleclassmodifiers=%{
// Custom C# Exception
  public class CustomException: global::System.ApplicationException {
  public CustomException(string message, int status) 
    : base(message) {
    m_status = status;
  }

  private int m_status;
  public int status
  {
      get => m_status;
      set => m_status = value;  
  }
}

public class%}

%typemap(throws, canthrow=1) ns::exception::CustomException{
  SWIG_CSharpSetPendingExceptionCustom($1.what(), (int)($1.status()));
  return $null;
}


/************************/
/**   Include Files   ***/
/************************/
%include "custom_exception.h"

Swig creates the exception .cs class, but unfortunately, I wasn't able to catch it via a csharp code.

I get the following message: Unhandled exception. System.Runtime.InteropServices.SEHException (0x80004005): External component has thrown an exception.

Can someone please point me to the right direction ( didn't find anything relevant on google)?

0

There are 0 best solutions below