Note: the full code for this example can be found in the project SafeCode in the Samples sub-directory.
Structured Exception Handling (SEH) is a 'C' language technique, which does not mix well with C++ code. The easiest way to integrate this kind of code into an XLL+ program is by converting the SEH exceptions to C++ exceptions. This conversion means that you an be sure that destructors will be called correctly in your C++ code, after the SEH exception occurs.
The code below shows a pair of classes that handle the integration into C++. One is a C++ exception class, and the other is a handler class that installs (and uninstalls) a C exception handler function, and converts C exceptions to C++ exceptions.
///////////////////////////////////////////////////////////////////////////// // C++ adapter for Structured Exception Handling #include <eh.h> class SE_Exception { private: unsigned long nSE; public: SE_Exception() {} SE_Exception(unsigned long n) : nSE(n) {} ~SE_Exception() {} unsigned long getSeNumber() { return nSE; } }; class SE_Handler { private: static void seh_trans_func(unsigned int u, EXCEPTION_POINTERS* pExp) { DWORD dwCode = (pExp && pExp->ExceptionRecord) ? pExp->ExceptionRecord->ExceptionCode : 0; throw SE_Exception((long)dwCode); } _se_translator_function fnOld; public: SE_Handler() { fnOld = _set_se_translator(seh_trans_func); } ~SE_Handler() { _set_se_translator(fnOld); } };
To use the handler class, you just have to instantiate one before calling dangerous code and ensure that it is destroyed soon afterwards.
The unsafe version looks something like this:
extern "C" __declspec( dllexport ) LPXLOPER INTAVG(const COper* Input) { CXlOper xloResult; BOOL bOk = TRUE; std::vector<long> vecInput; bOk = bOk && Input->ReadVector(vecInput, "Input", xloResult); if (!bOk) return xloResult.Ret(); //}}XLP_SRC xloResult = (double)IntAverage(vecInput.size(), &vecInput[0]); return xloResult.Ret(); }
The safe version (shown below) is different in two ways:
extern "C" __declspec( dllexport ) LPXLOPER INTAVG(const COper* Input) { CXlOper xloResult; BOOL bOk = TRUE; std::vector<long> vecInput; bOk = bOk && Input->ReadVector(vecInput, "Input", xloResult); if (!bOk) return xloResult.Ret(); //}}XLP_SRC try { SE_Handler seh; xloResult = (double)IntAverage(vecInput.size(), &vecInput[0]); } catch(SE_Exception e) { xloResult.Format("#ERROR: C exception 0x%lX", e.getSeNumber()); } return xloResult.Ret(); }