Difference between revisions of "How to use a Haskell Dll from Excel"

From HaskellWiki
Jump to navigation Jump to search
 
m
Line 1: Line 1:
 
== Context ==
 
== Context ==
   
This how-to extends the information found in the [http://www.haskell.org/ghc/dist/current/docs/users_guide/win32-dlls.html|12.6. Building and using Win32 DLLs] article. For build instructions and unchanged code, refer to this article.
+
This how-to extends the information found in the [http://www.haskell.org/ghc/dist/current/docs/users_guide/win32-dlls.html|12.6. Building and using Win32 DLLs] article. For build instructions and base code, refer to this article.
   
 
== Excel crash on Exit when using a GHC DLL ==
 
== Excel crash on Exit when using a GHC DLL ==

Revision as of 14:20, 3 December 2007

Context

This how-to extends the information found in the Building and using Win32 DLLs article. For build instructions and base 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.