天天看點

VS2010實作64位代碼調用32位子產品方法include include include import “E:\VC Codes\VS2010\OOPComTest\ComAddDemo\ComAddDemo\Debug\ComAddDemo.tlb” raw_interfaces_only, raw_native_types, no_namespace, named_guids

最近在做代碼更新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,“确定”——》“下一步”,在彈出的界面中“應用類型”中選擇第二項見下圖紅框圈出部分,然後“完成”。

  1. 添加接口類

    切換到類視圖,選中項目檔案,右鍵——》添加——類,在彈出的界面左側選擇ATL,右面選擇ATL簡單對象,見下圖。

點選“添加”,然後在彈出的向導界面中輸入類名和ProgID,其他參數預設,一路下一步到完成。

注意:1)這裡的ProgID一定要填,不然後面找不到入口将無法正确調用元件。

2)如果後面用到的時候忘記此處輸入的名稱,可以到“解決方案資料總管”視圖中的“資源檔案”中的ISimAddObj.rgs檔案中檢視,内容如下:

添加完成後,在類視圖的項目下會出現接口 。

3. 添加接口方法

選中上一步添加的接口,依次點選:右鍵——添加——方法,然後在向導界面中輸入方法名并添加輸入輸入參數,見下圖。這裡輸入參數勾選“in”;輸出參數先選擇LONG*類型,點亮“out”和“retval”,然後勾選“retval”。然後輸入參數名後“添加”即可。

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

切換到解決方案資料總管,展開“源檔案”,輕按兩下打開ComAddDemo.idl檔案,看到如下代碼,就是剛才定義的COM方法。

  1. 方法實作

    輕按兩下打開上面“源檔案”中的ISimAddObj.cpp檔案,調用步驟一中生成的Add.dll,編輯實作Add方法。如下圖:

  2. 編譯運作

    會生成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,為了保證輸出的檔案在同一目錄下,在項目向導界面中的解決方案選項如下,其他參數預設。

  1. 實作調用

    在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是元件注冊的腳本檔案,當你注冊元件時,元件内部便是調用了這個檔案。

  1. 運作結果

    編譯運作,結果如下:

  2. 實作64位調用

    在ComAddDemoTest項目中添加64位編譯選項,重新編譯運作,結果依然如上。

    至此,實作了64位代碼調用32位子產品的方案。至于參考文獻中提到的安全性問題,現在還沒有考慮,後面用到再學習。

    完整代碼可以在下面連結中下載下傳:

    https://download.csdn.net/download/yanmanm/10615236

繼續閱讀