Unmanaged Assemblies

昨日のVisual C++ 2005(というかコンパイラ、リンカ)の変更についてフォロー。

足し算、引き算をするライブラリ(math.cpp)を作ってみます。

#include <stdio.h>

extern "C" __declspec (dllexport) void add (int x, int y) {
    printf ("%d + %d = %d\n", x, y, x + y);
}

extern "C" __declspec (dllexport) void subtract (int x, int y) {
    printf ("%d - %d = %d\n", x, y, x - y);
}

で、コンパイル

$ cl /LD /MD math.dll

すると、

  • math.dll
  • math.dll.manifest
  • math.exp
  • math.lib
  • math.obj

これらのファイルが生成されます。.manifestという馴染みのファイルが混じっていますが、取りあえず今は気にしないことに。で、これを呼び出すプログラムを書きます。(app.cpp)

#include <stdio.h>

#pragma comment (lib, "math.lib")

extern "C" void add (int x, int y);
extern "C" void subtract (int x, int y);

void main () {
    add (10, 20);
    subtract (10, 20);
}

これも何の変哲もないコードですね。で、コンパイル

$ cl app.cpp

問題なくコンパイルされます。これを実行すれば、

 10 + 20 = 30
 10 - 20 = -10

が表示されるはずですよね。ところが、実行エラーになるんですよね。「app.exe - エントリ ポイントが見つかりません」とか言って。(^^;

ここで、先ほどのmath.dll.manifestを覗いてみましょう。

<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
  <dependency>
    <dependentAssembly>
        <assemblyIdentity type='win32' name='Microsoft.VC80.CRT' version='8.0.50608.0' 
            processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' />
    </dependentAssembly>
  </dependency>
</assembly>

Microsoft.VC80.CRTがmsvcrt80.dllの事で、このマニフェストが無いと共有アセンブリであるmsvcrt80.dllを読み込んでくれないのです・・・て、マニフェストあるだろっ!(^^; 実は、.dllの場合、リソースとして.dllに埋め込んでやる必要があるのです。

$ mt /manifest math.dll.manifest /outputresource:math.dll;#2

最後の#2はリソースIDで、.dllの時は必ず2になります。改めてapp.exeを実行すると今度は実行されます。

知らないと結構嵌りそうですね〜(^^;