Я потратил последний день на поиск документации, просмотр сообщений на форуме и поиск в Google, чтобы попытаться сделать что-то, что, как я предполагаю, может быть легко сделано с правильной информацией.
У меня очень большое существующее приложение C ++на котором уже определен COM-сервер со многими методамиЯ пытаюсь использовать эти методы COM в приложении C # (у меня есть опыт работы с C ++, но я новичок в C #).
Так что в моем приложении VS2010 C # я добавляю сервер COM в качестве ссылки.Методы COM видны в браузере объектов, и передача однозначных строк, чисел с плавающей запятой и целых чисел, кажется, работает нормально.
Но я в тупике, пытаясь прочитать значения SAFEARRAY, переданные из COM-сервера C ++, в C #приложение.В конце концов мне нужно передать строковые массивы с сервера C ++ в приложение C #, но при простом тестировании передачи массива с плавающей точкой у меня есть код, который строит, но происходит сбой со следующим исключением, когда я пытаюсь привести System.Object, содержащий массив с плавающей точкойto (float []),
"exception {System.InvalidCastException: невозможно преобразовать объект типа 'System.Object []' в тип 'System.Single []'."
С помощью intellisence я вижу, что Object содержит правильный массив чисел с плавающей запятой длиной 8760, но я не могу получить доступ к этим данным в C #.
Вот код на стороне C # (d2RuleSet - это интерфейс, определенный вCOM-сервер DOE2Com).Выше приведено исключение в последней строке ниже.
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);
Ниже приведен код C ++, где VARIANTданные загружены.
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, но, возможно, я там тоже что-то пропустил).
----------------- Конец оригинального вопроса ------------------------------------------------------ Я редактирую, чтобы опубликовать код из успешного решения 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;
}