How to use a Haskell Dll from Excel
Context
This how-to extends the information found in the Building and using Win32 DLLs article. For build instructions and unchanged code, refer to this article.
Excel crash on Exit when using a GHC DLL
Calling shutdownHaskell from the dllMain function, as in the given example can cause Excel to crash on exit.
As explained in section "12.6.3. Beware of DllMain()!" of the same article, it's safer to call startupHaskell and shutdownHaskell from outside DllMain.
Updated dllMain.c code
Here is an updated dllMain.c
code with additional initialization and shutdown functions.
#include <windows.h> #include <Rts.h> #define __ADDER_DLL_EXPORT #define ADDER_API _declspec(dllexport) extern void __stginit_Adder(void); static char* args[] = { "ghcDll", NULL }; /* N.B. argv arrays must end with NULL */ BOOL STDCALL DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ return TRUE; } ADDER_API BOOL adder_Begin(){ startupHaskell(1, args, __stginit_Adder); return HS_BOOL_TRUE; } ADDER_API void adder_End(){ shutdownHaskell(); }
VBA code for Dll initialization and shutdown
We must call adder_Begin
before any call to the DLL exported functions and adder_End
before the DLL is unload. Excel VBA provides us with two callback functions that seems appropriate for this: Workbook_Open
and Workbook_BeforeClose
.
Function declaration in Excel is extended to add the two initalization and shutdown functions. I put it in a new module so I can make them public. The code looks like this:
Public Declare Function adder Lib "adder.dll" Alias "adder@8" (ByVal x As Long, ByVal y As Long) As Long Public Declare Function adder_Begin Lib "adder.dll" () As Boolean Public Declare Sub adder_End Lib "adder.dll" ()
The callback functions have to be defined in the ThisWorkbook
module and look like this:
Private Sub Workbook_BeforeClose(Cancel As Boolean) adder_End End Sub Private Sub Workbook_Open() adder_Begin End Sub
Known problems
If closing Excel is canceled the Workbook_BeforeClose
function will be called and haskell will be shutdown leaving the Workbook open but with Haskell down. The application will crash on the next DLL function call. This is easy to reproduce, modify the WorkBook, close it without saving and press Cancel
. Change some value to cause a GHC function to be called and Enjoy Excel crashing.