[software]dlsym、GetProcAddressとname mangling

上でCとC++間での関数呼び出しの際にname manglingが壁になることを述べたが、C++で閉じている環境ではそんなことを普通は気にしなくていい。が、マイクロソフトの言う「明示的リンク]」というやつを使う場合は別だ。「明示的リンク」とはdlsymやGetProcAddressなどのAPIでDLLから目的の関数ポインタを得る方法でのDLLの使用のことを言うようである。
eVCでWindows CE向けの開発をしていると、C++が標準という気分になってしまう。筆者がこれではまったのもWindows CE向けプロジェクトだった。お客様から提供された、とある機能のDLLを使用することになったのだが、当初「暗黙的リンク」でリンクして納品したところ、そのDLLがない場合は別の方法を使用するようにして欲しい(つまり、そのDLLがなくても動作するように作って欲しい)と要求され、「明示的リンク」でリンクすることにした。そこで、やってみてはたと気がついたのだが、GetProcAddressに関数名を普通に渡しても失敗するのである。どうやらお客様(正確にはお客様が作業依頼している別のベンダだと思われるが)が、件のDLLをC++で作成し、シンボルがname manglingされているようだ。「暗黙的リンク」でリンクした場合にはこちらもC++コンパイラを使っていたから特にリンカエラーも出ずに気がつかなかった。そう、dlsymやGetProcAddressなどの「明示的リンク」で呼び出されることを考慮するならば、呼び出し側も含めてC++で閉じていようとも、extern "C"を指定して、name manglingしないようにするべきなのである。ちなみに、筆者が取るべき行動は、

  • 「お客様にDLLのシンボルのname manglingをやめてもらうようにお願いする」
  • 「dumpbinでexportされているシンボルをみて、GetProcAddressに渡すシンボル名を調べる」

のどちらかであった。正義感に燃えるエンジニアとしては前者を選びたいところだが、お客様を通してこのDLLを作成しているであろうベンダとやりとりするのが非常に面倒そうだったので、後者を採用してしまった。これも処世術である。