64位程序調用32位dll

轉自:https://blog.csdn.net/yanmanm/article/details/81870436

            https://blog.csdn.net/nie2314550441/article/details/49867735

最近在做代碼升級64位,因爲有些第三方的模塊沒有源碼,所以需要用到64位代碼調用32位模塊的方案,在網上找了很多資料和方法,最終參考國外的一篇文章解決了問題,原理是應用進程外com實現,具體見參考文獻:

https://blog.mattmags.com/2007/06/30/accessing-32-bit-dlls-from-64-bit-code/

現在爲了更多的朋友少走彎路,這裏把我實現的過程和源碼跟大家分享。

步驟一:生成32位模塊(如果已經有32位模塊,這步驟可以跳過) 
新建MFC DLL項目,項目名稱爲Add,新建接口文件AddExport.h然後添加接口方法AddMethod,實現兩個整數的求和操作,聲明如下: 
int AddMethod(int num1, int num2); 
編譯生成32位的Add.dll模塊。

步驟二:建立進程外Com,對32位模塊進行封裝 
因爲此步驟是關鍵步驟,所以寫明具體操作步驟。 
1. 新建ATL項目 
項目名稱爲ComAddDemo,“確定”——》“下一步”,在彈出的界面中“應用類型”中選擇第二項見下圖紅框圈出部分,然後“完成”。

添加接口類 
切換到類視圖,選中項目文件,右鍵——》添加——類,在彈出的界面左側選擇ATL,右面選擇ATL簡單對象,見下圖。
點擊“添加”,然後在彈出的嚮導界面中輸入類名和ProgID,其他參數默認,一路下一步到完成。

注意:1)這裏的ProgID一定要填,不然後面找不到入口將無法正確調用組件。 
2)如果後面用到的時候忘記此處輸入的名稱,可以到“解決方案資源管理器”視圖中的“資源文件”中的ISimAddObj.rgs文件中查看,內容如下:

添加完成後,在類視圖的項目下會出現接口 。 
3. 添加接口方法 
選中上一步添加的接口,依次點擊:右鍵——添加——方法,然後在嚮導界面中輸入方法名並添加輸入輸入參數,見下圖。這裏輸入參數勾選“in”;輸出參數先選擇LONG*類型,點亮“out”和“retval”,然後勾選“retval”。然後輸入參數名後“添加”即可。

在“下一步”的界面中,可以在紅框圈出的位置添加此方法的說明信息,然後點“完成”即可。

切換到解決方案資源管理器,展開“源文件”,雙擊打開ComAddDemo.idl文件,看到如下代碼,就是剛纔定義的COM方法。

方法實現 
雙擊打開上面“源文件”中的ISimAddObj.cpp文件,調用步驟一中生成的Add.dll,編輯實現Add方法。如下圖:

編譯運行 
會生成32位的ComAddDemo.exe文件,並自動註冊到系統中。 
本步驟問題及解決: 
1) 我在Win10 64位系統上編譯的,出現下面錯誤信息 
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: The command “”E:\VC Codes\VS2010\OOPComTest\ComAddDemo\Debug\ComAddDemo.exe” /RegServer 
1>C:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\Microsoft.CppCommon.targets(113,5): error MSB3073: :VCEnd” exited with code -2147024891. 
這是Windows權限問題,導致註冊失敗,退出VS2010,然後選中VS2010圖標,右鍵選中“以管理員身份運行”,打開剛纔的解決方案,重新編譯ComAddDemo項目即可。 
2) 用到的Add.dll需要和ComAddDemo.exe在同一目錄下,才能註冊成功。

步驟三:調用COM模塊 
1. 新建Win32控制檯項目 
項目名ComAddDemoTest,爲了保證輸出的文件在同一目錄下,在項目嚮導界面中的解決方案選項如下,其他參數默認。

實現調用 
在SDK中調用最簡單最常用的一種,用#import導入類型庫,利用VC提供的智能指針包裝類。 
在解決方案資源管理器視圖中雙擊ComAddDemoTest.cpp文件,實現代碼如下: 
// ComAddDemoTest.cpp : Defines the entry point for the console application. 
// 
*#include “stdafx.h”
include
include
include
import “E:\VC Codes\VS2010\OOPComTest\ComAddDemo\ComAddDemo\Debug\ComAddDemo.tlb” raw_interfaces_only, raw_native_types, no_namespace, named_guids
in*t _t**main(int argc, _TCHAR* argv[]) 

long num1 = 10; 
long num2 = 20; 
long sum = 0; 
CoInitialize(NULL); 
CLSID clsid; 
IISimAddObj* pProxy; 
HRESULT hr = CLSIDFromProgID(OLESTR(“ComAddDemo.SimAddObj”), &clsid);//這裏的字符串一定要和註冊表中的ProgID一致!!!

hr = CoCreateInstance(clsid, NULL, CLSCTX_LOCAL_SERVER, IID_IISimAddObj, (void **)&pProxy); //創建COM對象
pProxy->Add(num1, num2, &sum); //調用COM接口
CoUninitialize();
printf("%d + %d = %d", num1, num2, sum);
return 0;


關於CLSIDFromPro*g*ID(OLESTR(“ComAddDemo.SimAddObj”), &clsid)中的字符串ComAddDemo.SimAddObj,跟步驟二-2中的ProgID有關,如果忘記請在ComAddDemo.rgs文件中找(直接在磁盤文件中打開或者參考步驟二-1中的注意事項)。rgs是組件註冊的腳本文件,當你註冊組件時,組件內部便是調用了這個文件。

運行結果 
編譯運行,結果如下:

實現64位調用 
在ComAddDemoTest項目中添加64位編譯選項,重新編譯運行,結果依然如上。

至此,實現了64位代碼調用32位模塊的方案。至於參考文獻中提到的安全性問題,現在還沒有考慮,後面用到再學習。 
完整代碼可以在下面鏈接中下載: 
https://blog.csdn.net/yanmanm/article/details/81870436

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章