

-- Adder.hs

{-# LANGUAGE ForeignFunctionInterface #-}

module Adder where



adder :: Int -> Int -> IO Int -- gratuitous use of IO

adder x y = return (x+y)



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





// StartEnd.c

#include <Rts.h>



extern void __stginit_Adder(void);



void HsStart()

{

int argc = 1;

char* argv[] = {"ghcDll", NULL}; // argv must end with NULL



// Initialize Haskell runtime

char** args = argv;

hs_init(&argc, &args);



// Tell Haskell about all root modules

hs_add_root(__stginit_Adder);

}



void HsEnd()

{

hs_exit();

}



Adder



$ ghc -c Adder.hs

$ ghc -c StartEnd.c

$ ghc -shared -o Adder.dll Adder.o Adder_stub.o StartEnd.o



HsStart

HsEnd

DllMain

hs_init

hs_exit

-threaded



Private Declare Function Adder Lib "Adder.dll" Alias "adder@8" _

(ByVal x As Long, ByVal y As Long) As Long



Private Declare Sub HsStart Lib "Adder.dll" ()

Private Declare Sub HsEnd Lib "Adder.dll" ()



Private Sub Document_Close()

HsEnd

End Sub



Private Sub Document_Open()

HsStart

End Sub



Public Sub Test()

MsgBox "12 + 5 = " & Adder(12, 5)

End Sub



Document_Open

Close

HsStart

HsEnd



// Tester.cpp

#include "HsFFI.h"

#include "Adder_stub.h"

#include <stdio.h>



extern "C" {

void HsStart();

void HsEnd();

}



int main()

{

HsStart();

// can now safely call functions from the DLL

printf("12 + 5 = %i

", adder(12,5)) ;

HsEnd();

return 0;

}





$ ghc -o tester Tester.cpp Adder.dll.a

$ tester

12 + 5 = 17



The current section of the GHC manual on creating DLL's on Windows is fairly confusing to read, and has some bugs (i.e. 3605 ). Since I got tripped up by the current documentation, I offered to rewrite sections 11.6.2 and 11.6.3 (merging them in the process). Creating Windows DLL's with GHC is surprisingly easy, and my revised manual section includes an example which can be called from both Microsoft Word (using VBA) and C++. I've pasted the revised manual section as the rest of this blog post. I'll shortly be submitting it to the GHC team, so any feedback is welcome.This section describes how to create DLLs to be called from other languages, such as Visual Basic or C++. This is a special case of Section 8.2.1.2, "Making a Haskell library that can be called from foreign code" ; we'll deal with the DLL-specific issues that arise below. Here's an example:Use foreign export declarations to export the Haskell functions you want to call from the outside. For example:Add some helper code that starts up and shuts down the Haskell RTS:Here,is the name of the root module in the module tree (as mentioned above, there must be a single root module, and hence a single module tree in the DLL). Compile everything up:Now the file Adder.dll can be used from other programming languages. Before calling any functions in Adder it is necessary to call, and at the very end callNOTE: It may appear tempting to useto call, but this won’t work (particularly if you compile with).An example of using Adder.dll from VBA is:This example uses thefunctions of Microsoft Word, but providedis called before the first function, andafter the last, then it will work fine.An example of using Adder.dll from C++ is:This can be compiled and run with: