STDCALL対策:VC用暗黙的リンクのライブラリ編集ツール(ソース公開)

  DLLを暗黙的リンクする時、インポートライブラリを使用する。
  よくDLLを使うプログラマーたちはこのパターンに詳しいと思う:DEFファイルを書く→LIB.EXEツールでDEFファイルからLIBファイルに変更する→自分のコードにリンクする。
しかしこの場合に、このパターンはよく効けない:

  1. コンパイラーはVC
  2. 関数かStdcall型
  3. エクスポートする識別子に @nn がない

  原因は、VCはソースコード中の関数名を装飾を付く。
  普段で、C言語の場合「int add(int, int);」あるいはC++言語の場合「extern "C" int add(int, int)」という関数は、識別子が_addになる。リンクの時_addと言う識別子を探す。例えばDEFファイルに「add」で書いたらDLLに「add」と言う関数にリンクする、識別子は「_add」。これはデフォルトの「Cdecl」。
  しかし、Stdcall修飾は存在する場合「int __stdcall add(int, int);」の関数の識別子は「_add@8」になる。Cdeclで使う手段はうまく行わなくなる。リンクの時リンカーは識別子「_add@8」を探すが、LIB.exeで作成したインポートライブラリは「_add」しかない。この時エラーが出る。
  対策としてDEFファイルに「add@8」と書いてもうまく行わない。確かにリンカーにエラーが出ないけど、exeを実行する時エラーが出る:DLL側は装飾つきない関数名としてエクスポートする。しかも、EXE側は関数の修飾をCdeclに変更してもダメだ。クラッシュを発生する:関数の引数はアセンブラレベルで呼ばれた関数側で解放して、呼出元ではないから、修飾の変更することは正しくない。
  この問題の対策として、自分はこのツール( http://d.hatena.ne.jp/sorayukinoyume/20140129 )作ったが、この方法はマジで複雑すぎる:VCのリンカーはインポートテーブルを構築する方法を勉強して、バイナリレベルでSectionを構築して、Coff Objectを構築して、最後でLibraryを構築する。うまく実行できるまでコードを書いてデバックして半月ほど掛かった。ツールは使えるが、私はまた何か簡単な方法があるのかなって思って、結局方法を探した。
  MinGWツールセットでdlltoolと言うツールがある。LIB.exeのようなDEFからLIBを作成する機能もあるが、こいつ--kill-atと言うパラメータがある。このパラメータは簡単に言えばDEFファイルの書く「add@8」はリンカー側に識別子は「_add@8」がDLL側に「add」と言う関数にリンクする。もしLIB.exeにもこんな機能があれば・・・
  実はね、VCのインポートライブラリにこういう機能があるが、LIB.exeに実装してないだけ。そして、私はツールを書いて、こんな機能を実装した。LIB.exe /out:xxx.lib /def:xxx.defで作成したLIBファイルを編集するツール。

2014-2-3更新した
変更点:exeはx86として構築する。新しいPC買ってx64のOSを使ってなんかこのツールはうまく動けなくなった。DLLはx86ですから
ダウンロード:http://www1.axfc.net/u/3169399.7z
ソースは変更してない

2014-2-3更新した
.net framework 4.0は必要だ。
ダウンロード:http://www1.axfc.net/u/3162102.zip
Visual Studio 2013 Express、C++/C#。ATL 7.1は必要だ。
ソースコード:http://www1.axfc.net/u/3162104.zip

参考:
インポートライブラリの仕様:
http://msdn.microsoft.com/ja-jp/windows/hardware/gg463119.aspx

MinGW GCCでDLLを使おうとしたがよく分からない:
http://d.hatena.ne.jp/y2q_actionman/20070628

DLL作成の指針やDLLに関連するファイルについて:
http://www.ne.jp/asahi/hishidama/home/tech/vcpp/dllusage.html