Excelとかで呼び出すWINAPI系DLLをclangで作る
clangで作ったDLLをExcelから呼べなくてはまったので解決法をメモ。
clangでWINAPIをつけた関数
- 「ExportedFunction@20」みたいに「@
」付きでexportされる - clangというよりは、MinGWのldがそういう動作をしている模様
- 「@
」関数しか無い状態だと「エントリ"ExportedFunction"がDLLファイル"WinapiCallingConvention-clang.dll"内に見つかりません。」的なエラーメッセージが出てDLL関数呼び出しができない
解決法
- リンカオプションに「--add-stdcall-alias」を追加する
オプションをつけると「@
objdumpとかでエクスポートテーブルを確認するとこんな感じになる。(必要箇所を抜粋)
C:\clang-excel-dll-test>objdump -x WinapiCallingConvention-clang.dll
[ 0] ExportedFunction
[ 1] ExportedFunction@20
makefile
例えばmakefileはこんな感じにする。
CFLAGS = -Wall -W -fPIC -fvisibility=hidden LFLAGS = -shared -static -Wl,--add-stdcall-alias INCS = LIBS = CC = clang TARGET = WinapiCallingConvention-clang.dll SRCS = \ main.c \ OBJS = $(SRCS:.c=.o) .PHONY: all debug clean delete_objs delete_target all: CFLAGS += -O2 all: $(TARGET) debug: CFLAGS += -g debug: LFLAGS += -g debug: $(TARGET) clean: delete_objs delete_target delete_objs: del /f /q $(OBJS) delete_target: del /f /q $(TARGET) .SUFFIXES: .c .o .c.o: $(CC) $(INCS) -c $(CFLAGS) $< $(TARGET): $(OBJS) $(CC) -o $@ $(OBJS) $(LFLAGS) $(LIBS)
余談
今回も無駄にはまってしまった。
などのキーワードでググってもdlltoolとかdefファイルばかり引っかかるし。
それらを試したり内容を読んだりしたりで時間がかかった。
最終的にふと「そういえば、DLL作ってるのはリンカだよね」と思いだして、MinGWのldについて調べたり「ld --help」を打ってようやくそれっぽいオプションを見つけて試してみてようやくうまく動いた。
なんというか、目の前の現象も大事だけどツールとかがどういう仕組みで動いているかを想像して問題個所を絞り込めないと回り道しちゃうね。
特にclangはバックエンドで仕事しているツールたちを意識しないと原因にたどり着けないねぇ。
*1:というか、「__stdcall」をつける