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できていないことがわかります。そう。これを何とかしたい。
コメントをお書きください