· 

32bit DLLを64bitアプリから使う(1)

32bit DLLを64bitアプリからcallすることはできません。今、何かの32bit DLLを持っているとして、これの64bit版が必ず入手できるとは限らない。そして、世の中は64bit化していって64bit DLLしか存在しないって状況もあり得る。ということは、64bitアプリから64bitDLLだけでなく32bitDLLを読み出さないといけないっていう需要は必ずある。

ちなみにMicrosoftはこう言っている。「アウトプロセス COM サーバーでラップ」しろ、、、と。なんとも難しいことを言う。

さらに、これを汎用的に実現したDLL Wrapperというものもある。

が、自力でやってみたい。というか、動くサンプルができればそれでいい。

「32bit dll call」とかでググるとあちこちのQ&Aでも、だいたい「dllを64bitで再ビルドすればいいじゃん」的な身も蓋もない回答を書いているその手の専門家?の人がいるけど、、、違う、そうじゃない

まずは、動作する32bitアプリと32bitDLLとを作ってみる。こちらを起動して、

で、VisualStudioCodeを起動。

VSCodeでこんな感じでファイルを作っていきます。

MyDLL32.cpp

#include <windows.h>

extern "C" int __stdcall tasu(int arg1,int arg2);
extern "C" int __stdcall hiku(int arg1,int arg2);
//extern "C" float __stdcall pi(void);


extern "C" int __stdcall tasu(int arg1,int arg2){
    return arg1+arg2;
}
extern "C" int __stdcall hiku(int arg1,int arg2){
    return arg1-arg2;
}

//extern "C" float __stdcall pi(void){
//    return 3.14159265358979;
//}

MyDLL32.def

LIBRARY MyDLL32
EXPORTS
    tasu
    hiku

testMyDLL32.c

#include <windows.h>
#include <stdio.h>

#define MyDLL32 "MyDLL32.dll"

typedef int (__stdcall *tasu_type)(int arg1,int arg2);
typedef int (__stdcall *hiku_type)(int arg1,int arg2);
//typedef int (__stdcall *pi_type)(void);
HMODULE dll;
tasu_type ptasu;
hiku_type phiku;
//pi_type ppi;

int main(int argc,char** argv){
    int arg1=10;
    int arg2=3;
    int wa,sa;
    dll=LoadLibrary(MyDLL32);
    if(dll==NULL){
        printf("Failed to load dll.\n");
        return -1;
    }
    ptasu=(tasu_type)GetProcAddress(dll, "tasu");
    phiku=(hiku_type)GetProcAddress(dll, "hiku");
    //ppi=(pi_type)GetProcAddress(dll, "pi");
    wa=ptasu(arg1,arg2);
    sa=phiku(arg1,arg2);
    printf("%d + %d = %d\n",arg1,arg2,wa);
    printf("%d - %d = %d\n",arg1,arg2,sa);
    //printf("pi = %f\n",ppi());
    FreeLibrary(dll);
    return 0;
}

Makefile

CC="C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x86\cl.exe"
LINK="C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x86\link.exe"

test32 : MyDLL32.dll testMyDLL32.exe
    .\testMyDLL32.exe

MyDLL32.dll : MyDLL32.obj
    $(LINK) /DLL /out:MyDLL32.dll /DEF:MyDLL32.def MyDLL32.obj

MyDLL32.obj : MyDLL32.cpp
    $(CC) /c MyDLL32.cpp

testMyDLL32.exe : testMyDLL32.C
    $(CC) testMyDLL32.c

clean:
        del MyDLL32.dll testMyDLL32.exe MyDLL32.obj testMyDLL32.obj

で、Terminalを起動。

で、

nmake test32

ってやると、ちょうダサいMakefileに従ってBuildして実行してくれる。

PS C:\Users\hoge\Documents\mscpp-vscode\projects\dll32-study\dll32> nmake test32

 

Microsoft(R) Program Maintenance Utility Version 14.29.30145.0

Copyright (C) Microsoft Corporation.  All rights reserved.

 

        "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x86\cl.exe" /c MyDLL32.cpp

Microsoft(R) C/C++ Optimizing Compiler Version 19.29.30145 for x86

Copyright (C) Microsoft Corporation.  All rights reserved.

 

MyDLL32.cpp

        "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x86\link.exe" /DLL /out:MyDLL32.dll /DEF:Mdll dll /DEF:MyDLL32.def MyDLL32.obj

Microsoft (R) Incremental Linker Version 14.29.30145.0

Copyright (C) Microsoft Corporation.  All rights reserved.

 

   ライブラリ MyDLL32.lib とオブジェクト MyDLL32.exp を作成中

        "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x86\cl.exe" testMyDLL32.c

Microsoft(R) C/C++ Optimizing Compiler Version 19.29.30145 for x86

Copyright (C) Microsoft Corporation.  All rights reserved.

 

testMyDLL32.c

Microsoft (R) Incremental Linker Version 14.29.30145.0

Copyright (C) Microsoft Corporation.  All rights reserved.

 

/out:testMyDLL32.exe

testMyDLL32.obj

        .\testMyDLL32.exe

10 + 3 = 13

10 - 3 = 7

PS C:\Users\hoge\Documents\mscpp-vscode\projects\dll32-study\dll32>

で、うまいこといっているのがわかります。

すなわち32bitDLLが出来上がって、32bitアプリからCallできたってこと。

では64bitアプリからCallしてみます。

こんな感じで、ファイルを作ります。

testMyDLL64.c

(32bitアプリと同じ。)

#include <windows.h>
#include <stdio.h>

//#define MyDLL32 "..\\dll32\\MyDLL32.dll"
#define MyDLL32 "MyDLL32.dll"

typedef int (__stdcall *tasu_type)(int arg1,int arg2);
typedef int (__stdcall *hiku_type)(int arg1,int arg2);
//typedef int (__stdcall *pi_type)(void);
HMODULE dll;
tasu_type ptasu;
hiku_type phiku;
//pi_type ppi;

int main(int argc,char** argv){
    int arg1=10;
    int arg2=3;
    int wa,sa;
    dll=LoadLibrary(MyDLL32);
    if(dll==NULL){
        printf("Failed to load dll.\n");
        return -1;
    }
    ptasu=(tasu_type)GetProcAddress(dll, "tasu");
    phiku=(hiku_type)GetProcAddress(dll, "hiku");
    //ppi=(pi_type)GetProcAddress(dll, "pi");
    wa=ptasu(arg1,arg2);
    sa=phiku(arg1,arg2);
    printf("%d + %d = %d\n",arg1,arg2,wa);
    printf("%d - %d = %d\n",arg1,arg2,sa);
    //printf("pi = %f\n",ppi());
    FreeLibrary(dll);
    return 0;
}

Makefile

CC="C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\cl.exe"
LINK="C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\link.exe"

test64 : testMyDLL64.exe
        .\testMyDLL64.exe

testMyDLL64.exe : testMyDLL64.C
    $(CC) testMyDLL64.c

clean:
        del testMyDLL64.exe testMyDLL64.obj

で、32bitDLLをapp64フォルダにコピーする。

で、64bitの開発環境を起動する。

で、

カレントフォルダをapp64まで移動して、

nmake test64

で、実行。

**********************************************************************

** Visual Studio 2019 Developer Command Prompt v16.11.15

** Copyright (c) 2021 Microsoft Corporation

**********************************************************************

[vcvarsall.bat] Environment initialized for: 'x64'

 

C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools>cd /d C:\Users\hoge\Documents\mscpp-vscode\projects\dll32-study\app64

 

C:\Users\hoge\Documents\mscpp-vscode\projects\dll32-study\app64>nmake test64

 

Microsoft(R) Program Maintenance Utility Version 14.29.30145.0

Copyright (C) Microsoft Corporation.  All rights reserved.

 

        "C:\Program Files (x86)\Microsoft Visual Studio\2019\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\cl.exe" testMyDLL64.c

Microsoft(R) C/C++ Optimizing Compiler Version 19.29.30145 for x64

Copyright (C) Microsoft Corporation.  All rights reserved.

 

testMyDLL64.c

Microsoft (R) Incremental Linker Version 14.29.30145.0

Copyright (C) Microsoft Corporation.  All rights reserved.

 

/out:testMyDLL64.exe

testMyDLL64.obj

        .\testMyDLL64.exe

Failed to load dll.

NMAKE : fatal error U1077: '.\testMyDLL64.exe' : リターン コード '0xffffffff'

Stop.

 

C:\Users\hoge\Documents\mscpp-vscode\projects\dll32-study\app64>

ビルドは成功しているのに、DLLをLoadできていないことがわかります。そう。これを何とかしたい。