Windows10 下64位程序調用32位dll


方法:

64位windows支持64位和32位進程(包括本機或跨機)間進程間通信(RPC)。在64位windows中,一個進程外32位COM服務器能夠與64位客戶端進行通信,同樣一個進程外64位COM服務器也能與32位客戶端進行通信。因此,如果你有一個32位COM無法識別的DLL,你可以將它封裝到一個進程外COM服務器中並在一個64位進程中用COM配置調用DLL。
原文鏈接:https://blog.csdn.net/nie2314550441/java/article/details/49867735

使用工具:

VS2017

步驟:

1.Devin已經驗證64位exe能調用32位dll,從他手中拿來Demo分析。

一共三個項目:

 

 ATLProject12->COM exe 32位 (64位程序通過COM exe 調用32位dll)

ConsoleApplication-> 64位程序

MFCLibrary3->32位dll

 

問題:項目copy后vs打開,把依賴項路徑什么的改了,發現代碼中的類或函數都不能直接F12。

原因:.vs這個文件夾沒有刪除,導致VS打開項目時,是根據之前同事電腦上的配置進行的加載。

 

 .vs文件夾:用來存儲當前用戶在解決方案中的工作配置,具體包括VS關閉前最后的窗口布局、最后打開的選項卡/操作記錄/文件文檔、某些自定義配置/開發環境、調試斷點等這類設置信息和狀態

參考鏈接:https://shiyousan.com/post/636441130259624698

 

2.

MFCLibrary:32位dll,會導出一個接口供ATLProject項目調用。

ATLProject12

ATL(類型庫):類型庫是idl文件、COM類文件,.h文件,.cpp文件,.def文件的綜合體。類型庫里面包含了我們所要用的COM組件(COM類)。我們經常使用的word、excel的COM組件,都是通過他們的類型庫導入客戶程序的,然后我們才能通過CoCreateInstance()來構建組件對象。類型庫就是COM類的容器,里面包含了若干COM類,是一個獨立的能被客戶程序導入的dll文件,是對COM組件的打包。

ATL作用:

ATL專門用來生成COM組件的,編譯后生成dll文件或者exe文件。

com組件和普通的dll文件有什么區別呢?

com組件優點:1.語言無關性;2.便於升級擴展;3.有很好的繼承封裝多態特性,即面向對象能力強;4.完成進程間,分布式功能;5.接口調用,便於組織。

 

VS創建一個ATL項目(必須要用管理員權限打開,不然最后編譯時會報錯 error MSB8011: 未能注冊輸出。PS:報這個錯也有可能是依賴項沒有全部配好)

 

選擇服務(.exe) 。

生成項目后新建項

 

ATL簡單對象

 

 

 

ProgID:

是在定義COM類時為類起的別名,方便程序員記住。命名規則為:ProjectName.ClassName.VersionNumber,即:工程名(類型庫名稱).類名(COM類名稱).(版本號)

在這里填一個自己能記住的先。

 

生成ATLSimpleObject.cpp和ATLSimpleObject.h

在.h和.cpp中添加需要導出的接口及實現

 

 

 源文件中有一個idl文件

 

 

 

 在interface里面添加前面寫好的需要導出的接口,[in]:表示傳入參數,[out]:表示傳出參數。基礎變量不用改變,string字符串需要用BSTR轉。或使用VARIANT變量傳遞參數

生成,產生一個ATLProject_i.c 和 ATLProject_i.h(.h中有導出的函數的聲明)。把這兩個文件添加到64位項目下,就能直接調用接口。

 

驗證過程中參數傳遞的問題:

需要傳圖片進32位dll進行處理,並返回處理后的圖片,使用OpenCV3.0

返回Mat。

使用COM組件提供的VARIANT和SAFEARRY(安全數組)進行Mat數據的傳遞。

VARIANT* matBackData;

SAFEARRAY *pArray1 = nullptr;
HRESULT hr = SafeArrayAllocDescriptor(1, &pArray1);//創建SAFEARRAY結構對象,在棧上
pArray1->cbElements = sizeof(unsigned char); //每個元素占用的字節數
pArray1->rgsabound[0].cElements = 5120 * 5120; //第0維數組元素個數
pArray1->rgsabound[0].lLbound = 0; //第0維數組起始下標
hr = SafeArrayAllocData(pArray1);//在堆上申請內存存放SAFEARRAY

上面這段代碼創建了一個5120 * 5120大小的安全數組

memcpy(pArray1->pvData, umatBackData, 5120 * 5120);

//pArray1->pvData = umatBackData;  //不能直接=。

umatBackData為需要放入安全數組的數據。這里umatBackData = mMat.data。mMat是處理后的圖片

matBackData->vt = VT_ARRAY | VT_UI1;//VT_VARIANT //SAFEARRAY的類型必須為VT_ARRAY, VT_UI1: 指明數組數據為unsigned char
matBackData->parray = pArray1;

matBackData可以成功返回數據。在調用端使用完后,需要釋放安全數組

SafeArrayUnaccessData(matBackData.parray);
SafeArrayDestroy(matBackData.parray);
VariantClear(&matBackData);

總結:

使用COM進行64位32位間的接口相互調用,和普通的32調32,64調64方法基本一樣,主要問題在於復雜結構的參數傳遞,可以使用COM提供的VARIANT和SAFEARRY對參數進行打包,然后傳遞。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM