我花了最後一天搜索文檔,查看論壇帖子和使用Google搜索來嘗試做一些我猜測可以輕鬆完成的正確信息。異常將VARIANT中的SAFEARRAY傳遞給C#從C++ COM服務器
我有一個非常大的現有C++應用程序,它有一個已經定義的COM服務器,並且有許多暴露的方法。我想在C#應用程序中使用這些COM方法(我在C++中經驗豐富,但是C#新手)。
因此,在我的VS2010 C#應用程序中,我添加了COM服務器作爲參考。 COM方法在對象瀏覽器中可見,並且傳遞單值字符串,浮點數和整數似乎工作正常。
但我很難將試圖讀取從C++ COM服務器傳遞到C#應用程序的SAFEARRAY值。最終,我需要將字符串數組從C++服務器傳遞到C#應用程序,但是在傳遞一組浮點數的過程中,我有構建的代碼,但是當我嘗試轉換包含浮點數組的System.Object時發生以下異常to(float []),
「異常{System.InvalidCastException:無法強制類型'System.Object []'的對象鍵入'System.Single []'。」
通過intellisence,我可以看到對象包含正確的8760長浮點數組,但我無法訪問C#中的數據。
這裏是C#端的代碼(d2RuleSet是在DOE2Com COM服務器中定義的接口)。上面的例外引發到下面的最後一行。
DOE2ComLib.DOE2Com d2RuleSet;
d2RuleSet = new DOE2ComLib.DOE2Com();
System.Int32 i_Series =0;
System.Object pv_WeatherData;
float[] faWeatherData;
iOut = d2RuleSet.GetWeatherData(i_Series, out pv_WeatherData);
Type typeTest;
typeTest = pv_WeatherData.GetType();
int iArrayRank = typeTest.GetArrayRank();
Type typeElement = typeTest.GetElementType();
faWeatherData = (float[])pv_WeatherData;
下面是在IDL文件中定義的C++ COM方法
HRESULT GetWeatherData([in] int iSeries, [out] VARIANT* pvWeatherData, [out,retval] int * piErrorCode);
下面是其中VARIANT數據被加載C++代碼部分。
void CDOE2BaseClass::GetWeatherData(int iSeries, VARIANT* pvWeatherData, int* piErrorCode)
{
*piErrorCode = 0;
if (iSeries < 0 || iSeries >= D2CWS_NumSeries)
*piErrorCode = 1;
else if (m_faWeatherData[iSeries] == NULL)
*piErrorCode = 3;
else
{
SAFEARRAYBOUND rgsaBound;
rgsaBound.lLbound = 0;
rgsaBound.cElements = 8760;
// First lets create the SafeArrays (populated with VARIANTS to ensure compatibility with VB and Java)
SAFEARRAY* pSAData = SafeArrayCreate(VT_VARIANT, 1, &rgsaBound);
if(pSAData == NULL) {
#ifndef _DOE2LIB
_com_issue_error(E_OUTOFMEMORY);
#else
//RW_TO_DO - Throw custom Lib-version exception
OurThrowDOE2LibException(-1,__FILE__,__LINE__,0,"OUT OF MEMORY");
#endif //_DOE2LIB
}
for (long hr=0; hr<8760; hr++)
{
COleVariant vHrResult(m_faWeatherData[iSeries][hr]);
SafeArrayPutElement(pSAData, &hr, vHrResult);
}
// Now that we have populated the SAFEARRAY, assign it to the VARIANT pointer that we are returning to the client.
V_VT(pvWeatherData) = VT_ARRAY | VT_VARIANT;
V_ARRAY(pvWeatherData) = pSAData;
}
}
預先感謝此問題的幫助,我覺得我花了什麼應該是一個簡單的問題太多時間。也請張貼任何涵蓋本地C++和C#之間互操作的鏈接或書籍(我認爲我已經通過大部分Visual Studio/MSDN文檔進行了ping操作,但也許我錯過了某些內容)。
-----------------原問題結束------------------------- ----------------------------- 我正在編輯發佈phoog下面成功解決方案的代碼,以便其他人可以閱讀和使用它。
int iOut = 0;
System.Int32 i_Series =0;
System.Object pv_WeatherData = null;
iOut = d2RuleSet.GetWeatherData(i_Series, out pv_WeatherData);
Type typeTest;
typeTest = pv_WeatherData.GetType();
int iArrayRank = typeTest.GetArrayRank();
Type typeElement = typeTest.GetElementType();
//float[] faWeatherData = (float[])pv_WeatherData;
float[] faWeatherData = ConvertTheArray((object[])pv_WeatherData);
....
float[] ConvertTheArray(object[] inputArray)
{
float[] result = new float[inputArray.Length];
for (var index = 0; index < result.Length; index++)
result[index] = (float)inputArray[index];
return result;
}
您確定'pv_WeatherData'中的數據是IEEE單浮點數而不是雙倍嗎?如果將它轉換爲Object []或Array,並在調試器中檢查它,會發生什麼?哦,我只是注意到它確實是一個InvalidCastException。你有錯誤的類型,需要投射。 – codekaizen 2012-02-21 23:23:31
在另一種情況下會發生什麼?例如如果我有一個C++函數在我的C#應用程序中使用,並且函數期望收到一個矩陣,例如:MyUnmanagedFunction(&Array);我如何傳遞數組? – willyMon 2014-11-28 04:10:53