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 ==
 
 
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 ==
 
 
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 <code>dllMain.c</code> code with additional initialization and shutdown functions.
 
 
<pre>
 
#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();
 
}
 
</pre>
 
 
== VBA code for Dll initialization and shutdown ==
 
 
We must call <code>adder_Begin</code> before any call to the DLL exported functions and <code>adder_End</code> before the DLL is unload. Excel VBA provides us with two callback functions that seems appropriate for this: <code>Workbook_Open</code> and <code>Workbook_BeforeClose</code>.
 
 
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:
 
 
<pre>
 
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" ()
 
</pre>
 
 
The callback functions have to be defined in the <code>ThisWorkbook</code> module and look like this:
 
 
<pre>
 
Private Sub Workbook_BeforeClose(Cancel As Boolean)
 
adder_End
 
End Sub
 
 
Private Sub Workbook_Open()
 
adder_Begin
 
End Sub
 
</pre>
 
 
== Known problems ==
 
 
If closing Excel is canceled the <code>Workbook_BeforeClose</code> 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 <code>Cancel</code>. Change some value to cause a GHC function to be called and Enjoy Excel crashing.
 

Revision as of 16:49, 3 December 2007