[Haskell-cafe] FFI and Excel VBA

Lewis-Sandy, Darrell darrelll at amgen.com
Thu Jun 21 11:05:30 EDT 2007


Whoops - I posted the wrong version of the exports list.  Compilation with
that adder.def will fail (since it the Haskell code doesn't export either
suber or hello).  Below is the revised example:

KEYWORDS: Foreign, Export, Win32, DLL, VBA, Excel, GCH, Example

The contents of adder.hs are as follows:
--------------------------------------------
module Adder(adder) where

import Foreign

adder :: Int -> Int -> IO Int
adder x y = return (id$!(x+y))

foreign export stdcall adder :: Int -> Int -> IO Int
--------------------------------------------

The contents of the dllMain.c file are below:
--------------------------------------------

#include <windows.h>
#include <Rts.h>

extern void __stginit_Adder(void);

static char* args[] = { "ghcDll", NULL };

BOOL STDCALL DllMain ( HANDLE hModule, DWORD reason, void* reserved ) {
  if (reason == DLL_PROCESS_ATTACH) {
      startupHaskell(1, args, __stginit_Adder);
      return TRUE;
  }

  if (reason == DLL_PROCESS_DETACH) {
        shutdownHaskell();
        return TRUE;
  }

  return TRUE;
}

--------------------------------------------
Note that the GHC manual omits the space between the "void" and the
__stgint_Adder(void) which causes a compile error.  The second case (if
(reason == DLL_PROCESS_DETACH) is essential for garbage collection, and
shuts down the Haskell runtime when the DLL is unloaded.

To execute the Haskell code, I created a VBA module in an Excel workbook
with the following code snippet:
--------------------------------------------
Private Declare Function adder Lib "adder.dll" _
  (ByVal x As Integer, ByVal y As Integer) As Integer

Private Sub test()
Debug.Print adder(1, 2)
End Sub
--------------------------------------------
NOTE: If the dll is not ultimately placed in your environments' PATH, then
you may have to modify the library name to include the actual path
information (or else you will get an error indicating that the library can't
be found).  Example:  ... adder Lib "c:\myDlls\adder\adder.dll" ...

Finally, you need to explicitly define an exports file to keep the c
compiler from mangling the names too badly.  The contents of adder.def are
as follows:
--------------------------------------------
EXPORTS
   adder
--------------------------------------------

With these preliminaries out of the way, you can compile this to a dll using
the following sequence of commands:
--------------------------------------------
ghc -c adder.hs -fglasgow-exts
ghc -c dllMain.c
ghc --mk-dll -optdll--def=adder.def -o adder.dll adder.o adder_stub.o
dllMain.o
--------------------------------------------

When this is all done, open the XLProject and press F5 to run, or simply
type "=adder(1,2)" in any cell of the workbook. 

My apologies for any confusion caused by my earlier posting.

-Darrell Lewis-Sandy
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe at haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe


More information about the Haskell-Cafe mailing list