Haskell from Excel
HaskellのモジュールをExcelから呼び出す方法がかかれたBlogをみつけたので、実際に自分の環境でやってみました。
Calling Haskell from Excel
http://flxldn.tumblr.com/post/163596541/calling-haskell-from-excel
しかし環境が違うためか、残念ながらできませんでした。せっかくなので覚えとして書きたいと思います。
(いろいろやってみてXLLアドインの勉強にはありましたが・・)
C++からHaskellの呼び出し、ExcelからのC++(XLL)呼び出しはできますが、つなげると以下のようなアラートがでました。

XLLは、xlw(A Wrapper for the Excel API)を使う方法と、Excel 2010 XLL SDKを使う方法と、二通りやりました。
参考)
xlw :http://xlw.sourceforge.net/
http://d.hatena.ne.jp/teramonagi/20110124/1295866787
xll sdk:
http://www.microsoft.com/en-us/download/details.aspx?id=20199
テスト環境 Excel 2010 + xlw ver5, Visual Studio 2010 / Windows 7
まずHaskellソースからDLLを作成します。
addr.hs
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
adder.h
#ifdef __cplusplus
extern “C”
{
#endif
__declspec(dllexport) void __stdcall HsBegin(void);
__declspec(dllexport) void __stdcall HsEnd(void);
__declspec(dllexport) long __stdcall adder(long x, long y);
#ifdef __cplusplus
}
#endif
adder.def
LIBRARY Adder EXPORTS adder@8=_adder HsBegin@0=_HsBegin HsEnd@0=_HsEnd
dllMain.c
static char* args[] = {"ghcDll" , NULL };
BOOL STDCALL DllMain( HANDLE hModule, DWORD reason, void* reserved)
{ return TRUE;}
__stdcall void HsBegin()
{
startupHaskell(1, args, __stginit_Adder);
}
__stdcall void HsEnd()
{
hs_exit();
}
以下コンパイル手順です。(VisualStudio2010コマンドプロンプト)
ghc -static -c adder.hs -fglasgow-exts
ghc -static -c dllMain.c
ghc -static -shared -o adder.dll adder.o adder_stub.o dllMain.o
lib /MACHINE:x86 /DEF:adder.def /OUT:adder.lib /NOLOGO /SUBSYSTEM:WINDOWS
出力されたadder.dllはSystem32フォルダにコピーします。
次に、XLLファイルを作成します。
xlwのインストールディレクトリの中にあるxlwTemplateExtractor.exe実行すると、XLL_Projectというフォルダがマイドキュメントに作成されるので、ここにあるソリューションを開きます。
デフォルトのEchoShortの下に追加して以下のようになります。
#include<cppinterface.h>
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) void __stdcall HsBegin(void);
__declspec(dllexport) void __stdcall HsEnd(void);
__declspec(dllexport) long __stdcall adder(long x, long y);
#ifdef __cplusplus
}
#endif
#pragma warning (disable : 4996)
short // echoes a short
EchoShort(short x // number to be echoed
)
{
return x;
}
short funcAdd(short d1, short d2){
return adder(d1, d2);
//return d1 + d2;
}
cppinterface.hにはfuncAddのプロトタイプを追加します。
xlwWrapper.cppというソースは自動で生成されるようです。
adder.libを参照するようにします。
まずコメントしてあるd1+d2で成功したことを確認してから、adderのテストしました。
すると上記アラートがでます。
ここで、HsBegin、HsEndを使い方を元のブログを見てみると、ライブラリ自体のmakeが必要のようだったのであきらめ、次にXLL SDKをテストしました。(ライブラリを変更してもたぶん結果は同じという気もしましたし)
XLL SDKをインストールしたフォルダ内にある、EXAMPLEプロジェクトを使用します。
他の関数を参考にして、
#define rgFuncsRows 30
static LPWSTR rgFuncs[rgFuncsRows][7] = {
....
{L"CalcCircum", L"BB", L"CalcCircum"},
{L"funcAdd", L"III", L"funcAdd"}
};
....
__declspec(dllexport) double WINAPI CalcCircum(double pdRadius)
{
return pdRadius * 6.283185308;
}
__declspec(dllexport) short WINAPI funcAdd(short x, short y)
{
return (short)adder((long)x,(long)y);
//return x + y;
}
このソースのxAutoOpen()、xAutoClose()にそれぞれHsBegin()、HsEnd()を追加。これらとadderの宣言部もxlwと同様に追加。
これもreturn x+yで動作確認後、Haskell呼び出し部をテストしました。それで上記アラートが出ました。
Excel-DNAてadder.dllを、とも思いましたが、あれはマネージDLLでした。
成果が何もないのもなんなので、cppコンソールアプリでHaskell呼び出しをしてみました。(adder.dllはexeと同じところに置く)
#include "stdafx.h"
#ifdef __cplusplus
extern "C"
{
#endif
__declspec(dllexport) void __stdcall HsBegin(void);
__declspec(dllexport) void __stdcall HsEnd(void);
__declspec(dllexport) long __stdcall adder(long x, long y);
#ifdef __cplusplus
}
#endif
int _tmain(int argc, _TCHAR* argv[])
{
HsBegin();
printf("adder : %d\n", adder(1,2));
HsEnd();
getchar();
return 0;
}
3 を表示します。
また解決したらつづきを書きたいと思います。