64位程序調用32位DLL


        近期再把原來寫的股票分析程序轉換成64位版本號,程序中調用了銀江的通視數據接口dll,由於銀江提供的dll是32位的,但windows以下64位程序並不能直接調用32位的dll,所以僅僅能百度了.
        網上有說用進程外com的方式能夠,之前從沒接觸過com,硬着頭皮搞了半天,發現了問題,進程外com對於dll提供函數返回值不涉及指針的話沒有不論什么問題,可是假設dll函數返回值是一個指針,問題就來了,因為這個指針和我自己的數據接收程序不在同一個進程地址空間,所以根本沒有辦法通過指針得到正確的接收數據.所以僅僅能放棄這種方法,轉向怎樣在進程間傳遞數據.
        我自己程序是用QT編寫,mingw編譯的,網上關於進程間通信(IPC)資料一大把,看了一下基本上QT在windows以下假設想在進程間傳遞大數據,僅僅能用LocalSocket或者共享內存的方式.兩種方式的基本思路幾乎相同,我自己的接收程序是64位的,另外在寫一個32位的server程序,負責調用銀江的數據接口dll,server程序接收到數據以后,以上面兩種方式傳遞給我64位的接收程序就能夠了. 
        首先以LocalSocket的方式來設計接口的,由於共享內存方式會設計比較麻煩的進程間同步問題,localsocket本身就有一條同步信號機制可供使用,詳細涉及使用QT的QLocalSocket,QLocalServer類,網上資料非常多,不贅述.既然是首先提這樣的方式,肯定是由於終於沒選他,理由是,localsocket會把我傳的整塊數據隨即切割,須要我在接收端推斷並又一次合成原始完整塊數據.這就要求接收端多余的推斷操作,和內存創建銷毀操作,終於還是放棄了.當然我並沒有太深入的去學習localsocket這樣的方式有沒有辦法不自己主動切割發送的完整大塊數據,假設有的話,這應該是一種理想的方式.
        以下就要講講我終於採用的共享內存方式了,主要涉及QT的QSharedPointer類,開3個共享內存;
        第1個用來存儲接收到的數據塊.
        第2個用來放接收端(64位)的winid,主要是提供給發送32位的dll調用端讀取,在接收到數據后通知64位的接收端有新的數據須要從共享內存中讀取;
        第3個共享內存區是同步信號區,存了一個整型變量,1代表等待64位client讀取數據,0代表沒有須要client讀取的數據.程序的初始狀態這個值為0,32位server端接收到新數據后,會先進入一個輪詢過程,在這個值為1時一直等待,僅僅有在這個值為0的時候才會打開數據共享區,並將數據放入共享區,之后再將這個值置為0.並發送給64位client通知消息(用windows的API,函數PostMessageW,里面目標窗體句柄就是第2個共享區中的數據);之后client收到消息以后,會先去讀取共享內存中的數據,將起copy到本地進程中,然后置這里的信號量置為0.
        共享內存方式基本就如上所述了,當然中間還是會有點小問題,由於接收到銀江數據頭是以下這種結構:
        typedef struct tagRCV_DATA
{
int m_wDataType; // 文件類型
int m_nPacketNum; // 記錄數,參見注一
RCV_FILE_HEADEx m_File; // 文件接口
BOOL m_bDISK; // 文件是否已存盤的文件
union
{
RCV_REPORT_STRUCTEx * m_pReport;
RCV_HISTORY_STRUCTEx * m_pDay;
RCV_MINUTE_STRUCTEx * m_pMinute;
RCV_POWER_STRUCTEx * m_pPower;
void * m_pData; // 參見注二
};
} RCV_DATA,*PRCV_DATA;
        能夠看出最后一個是個指針,這個指針指實際上在32位server端指向的是這個數據頭以下的緊接着的內存地址,可是這個地址是server進程中的絕對地址,到了64位client,假設仍然依照這個值,就不可能得到正確的數據,所以client不應該用這個值來對興許的數據訪問,而是在copy下來已經在本進程內存中的數據包的首地址上加上RCV_DATA這個數據包頭的大小(這里是288字節),這樣才干得到正確的興許數據地址.


免責聲明!

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



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