Получить элемент из SAFEARRAY (или преобразовать его в длинный массив)

Я пытаюсь получить элементы из SAFEARRAY (возвращенного как вывод функции) в Visual C++.

Я никогда раньше не пользовался SAFEARRAY, поэтому не знаю, как с ним обращаться. Должен ли я преобразовать SAFEARRAY в длинный массив (как?) или я могу просто использовать индекс значений внутри SAFEARRAY?


person merch    schedule 26.11.2013    source источник


Ответы (2)


Вероятно, вам следует ознакомиться с документацией SafeArray в MSDN.

Вероятно, вы захотите вызвать SafeArrayAccessData(), чтобы получить указатель на буфер памяти безопасного массива, а затем напрямую повторять значения. Вероятно, это самый эффективный способ доступа к значениям. В приведенном ниже коде многое предполагается, вы должны убедиться, что понимаете эти предположения (прочитав документацию по безопасному массиву) и что они применимы к вашей конкретной ситуации...

void Func(SAFEARRAY *pData)
{
   void *pVoid = 0;

   HRESULT hr = ::SafeArrayAccessData(pData, &pVoid);

   MyErrorCheck::ThrowOnFailure(hr);

   const long *pLongs = reinterpret_cast<long *>(pVoid);

   for (int i = 0; i < pData->rgsabound[0].cElements; ++i)
   {
      const long val = pLongs[i];

      DoThingWithLong(val);          
   }

   hr = ::SafeArrayUnaccessData(pData);

   MyErrorCheck::ThrowOnFailure(hr);
}

Обратите внимание, что приведенный выше код не видел компилятор...

person Len Holgate    schedule 26.11.2013
comment
В порядке! Я собираюсь прочитать документацию на MSDN. Но что мне действительно нужно, так это второй элемент SAFEARRAY, не могу ли я просто вызвать его с помощью индекса? Должен ли я повторять это? - person merch; 26.11.2013
comment
Нет, вам не нужно повторять это, вам нужно понимать часть rgsabound[] безопасного массива. И, как сказал Игорь, вы, вероятно, будете нести ответственность за уничтожение переданного вам массива. Если вам нужен ТОЛЬКО доступ ко второму элементу, используйте SafeArrayGetElement(). - person Len Holgate; 26.11.2013
comment
Я пытаюсь перебрать весь массив, чтобы лучше понять SAFEARRAY, используя приведенный ниже код; не могли бы вы сказать мне, почему это не работает? code : long lBound; long uBound; SafeArrayGetUBound(info, 1, &uBound); SafeArrayGetLBound(info, 1, &lBound); float item; for (long ind = lBound; ind < uBound; ind++) { SafeArrayGetElement(info, &ind, (void*)&item); array_tmp[ind] = item; } - person merch; 27.11.2013
comment
Следует сделать. Есть примеры на страницах MSDN и множество примеров кода в Интернете, которые должен найти Google. - person Len Holgate; 27.11.2013

См. SafeArrayGetElement или SafeArrayAccessData. Первый извлекает элементы один за другим. Последний дает вам указатель на плоский массив в стиле C, который обертывает этот экземпляр SAFEARRAY (не забудьте SafeArrayUnaccesData, когда закончите).

Также обратите внимание, что, скорее всего, вы несете ответственность за уничтожение массива (с SafeArrayDestroy), когда он вам больше не нужен.

person Igor Tandetnik    schedule 26.11.2013
comment
Большое тебе спасибо. Я только что видел эти функции, но не могу понять, в чем проблема; не могли бы вы сделать мне (или связать меня) пример обеих функций? - person merch; 26.11.2013