言語ゲーム

とあるエンジニアが嘘ばかり書く日記

Twitter: @propella

DLL に悩む

先日より非生産的な悩み方をしているが、あまりここで詰まっていても仕方が無いので、進むためにとりあえず今のところをメモ。

やりたい事

  • DLL を VC++ で作成する。暗黙的にリンク、明示的にリンクする。
  • DLL を cygwin で作成する。暗黙的にリンク、明示的にリンクする。

出来た事、出来ない事。

  • DLL を cygwin で暗黙的にリンク以外は出来る。
  • DLL を cygwin で暗黙的にリンク出来るようにすると、他の環境で同じ DLL を使えない。
  • 今の用途としては、明示的なリンクしか使わないのだが、なんとなく気持ち悪いので cygwin での暗黙リンクもしたい。

ちしき

  • DLL とは、プログラムの部品で、上手く作ればコンパイラや言語が違っても使いまわす事が出来る。
  • 暗黙的にリンクとは、プログラム起動時にシステムがリンクする事。コンパイル時には、DLL 自体の代わりに DLL の定義から作った小さな .a ファイルをリンクする。
  • 明示的にリンクとは、プログラム実行中にファイル名と関数名を指定して関数ポインタを取得して使う事。
  • 関数とは、プログラムの部品の事。名前が付いている。
  • エキスポートとは、プログラムの関数を外部から呼べるようにする事。エキスポートの仕方によって関数の名前が変わってしまう。
    • C++ で作成したプログラムの関数名は、かなり無茶苦茶変わるのでそのまま使えない。宣言を extern "C" {} で囲って使う。VC で .def ファイルを使えば extern は不要だが、cygwin では .def ファイルがあっても必要。
    • エクスポートする関数には、普通 __stdcall をつける。こうすると内部的に関数名の前に _ が付いて後ろに @引数サイズが付く(例: _function@8)。よくエラーで関数名の前に _ が付いているのはこの理由。
    • .def を使わない時、エクスポートする関数には __declspec(dllexport) が必要。インポートする関数には逆に __declspec(dllimport) が必要。ただし、cygwinコンパイルすると関数名に __imp_ が付いてしまって余計上手くいかない。
  • cygwin で dll をコンパイルするには以下のようにする。-Wl, は ld に渡されるオプションで、空白を続けてはならない。このコマンドによって .dll と .a ファイルが作られる。
    • gcc -shared -Wl,-k -Wl,--out-implib=prog.a -o prog.dll prog.cpp
  • 問題点: gcc で -Wl,-k オプションをつけると、関数名から @引数サイズ が消えて、VC でコンパイルしたプログラムともリンク出来る。しかし、その場合 cygwin のプログラムと暗黙リンク出来ない。

またあとで書き直す予定。