2010-11-02 118 views
1

我有一個C++ COM服務器,我最近重新編譯爲64位。這個COM服務器有一個包含struct參數的方法,該參數包含一些int和BSTR以及另一個結構。現在,我試圖從64位.Net C#應用程序調用此COM服務器。只要我不嘗試填充任何字符串參數,我就可以成功加載我的COM服務器並調用此方法。如果我嘗試在int成員中傳遞有效值,它們最終會在COM對象實現結束時損壞。看起來好像結構被編組的方式是錯誤的。這段代碼在32位應用程序中工作得很好。解決x64 com互操作問題

以下爲IDL是在C++側限定的一般方法:(忽略高飛的typedef,它的一些遺留碼)

[helpstring("method Method1")] HRESULT Method1([in] STRUCT1* pStruct, [in, out] DWORD* inparm1, [out]USHORT* outparm2); 


typedef struct _Struct2 
{ 
    USHORT p1; 
    BSTR s1; 
    BSTR s2; 
    BSTR s3; 
    BSTR s4; 
    DWORD  p2; 
    DWORD  p3; 
} STRUCT2; 


typedef struct _Struct1 
{ 
    DWORD p1; 
    DWORD p2; 
    BSTR s1; 
    BOOL p3; 
    STRUCT2 struct2; 
}STRUCT1; 

試圖填充構件在STRUCT2導致未定義的行爲和崩潰。任何人都可以看到爲什麼這將是64位詩句32位代碼的問題?是否有一些我需要發揮的編組魔法?此外,我似乎沒有工具來解決編組問題。有什麼建議可以幫助您排除打包者在封面上做的事情?

+0

順便說一下,我使用添加引用工具添加了對.NET項目的引用。 – 2010-11-02 22:11:29

回答

2

結構是COM的致命弱點。結構成員的實際佈局是高度依賴於編譯器的。他們在COM自動化方面不支持一段時間,直到他們提出IRecordInfo黑客攻擊。沒有在這裏使用。

在非託管代碼中,#pragma pack指令非常重要。對於類型庫,midl.exe的/ pack參數非常重要。如果它不是8或者你不使用64位版本的midl,那麼你一定會遇到這樣的問題。 BSTR成員是那些拋棄它的人,他們是32位或64位指針,具體取決於位數。 32位版本midl的倍數是4,而64位版本的倍數是8。只要結構不包含任何雙打,你可以通過傳遞/包4來拯救它。但首先嚐試64位版本的midl.exe。或者擺脫結構並用接口指針替換它們,那纔是真正的解決方案。

+0

謝謝。我將類型庫'is'導入到另一個C++應用程序時生成的.tlh文件拉出來,發現在每個包含BSTR的結構之前確實存在#pragma pack指令。我認爲這將幫助我朝着正確的方向前進。 – 2010-11-03 02:54:40