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();
}