Конвертировать VARIANT в ...? - PullRequest
2 голосов
/ 03 марта 2009

Примечание:

  • Попытка вызвать метод интерфейса, тип возвращаемого значения _variant_t

Код:

_variant_t resultsDataString;

_bstr_t simObjectNames;

simObjectNames = SysAllocString (L"TEST example 3");

resultsDataString = pis8->GetSimObject (simObjectNames);

встроенная функция , показанная ниже , содержится в .tli FILE:

inline _variant_t IS8Simulation::GetSimObject ( _bstr_t Name ) {
    VARIANT _result;
    VariantInit(&_result);
     HRESULT _hr = get_SimObject(Name, &_result);
   if (FAILED(_hr)) _com_issue_errorex(_hr, this, __uuidof(this));
    return _variant_t(_result, false);
}

Примечание:

  • resultsDataString имеет struct tagVARIANT:
    • VARTYPE vt равно 9 (без знака)
    • IDispatch Указатель интерфейса IDispatch

Вопрос

  • Как мне тогда преобразовать или извлечь значение?
  • Возможно использование VariantChangeType ?
  • Другой способ?

Edit:

Примечание:

  • В целях преобразования следующего кода Visual Basic в Visual C ++

  • MFC или ATL, если необходимо

  • В идеале, чистый C ++

Visual Basic эквивалент:

Public example1, example2 As SIMUL8.S8SimObject
Dim numberOfexamples As Variant
Dim resultString As Variant

Set example1 = MySimul8.SimObject("Example 1")
Set example2 = MySimul8.SimObject("Example 2")

numberOfexamples = example1.CountContents + example2.CountContents

resultString = CStr(numberOfexamples) & "*"

Ответы [ 4 ]

2 голосов
/ 04 марта 2009

Похоже, вы используете C ++ в качестве COM-клиента, полагаясь на встроенную поддержку COM компилятора VC ++. Чтобы упростить кодирование клиента, вы использовали #import для генерации классов-оболочек C ++, которые пытаются скрыть от вас все детали COM или, по крайней мере, упростить детали COM. Таким образом, вы не используете COM SDK напрямую, а используете клиентскую платформу (я думаю, что она представляет собой облегченную платформу только для COM, похожую на ATL или MFC).

Однако ваш пример кода, похоже, смешивает прямой низкоуровневый COM SDK (VARIANT s, BSTR, SysAllocString) с #import COM-фреймворком (_variant_t, _bstr_t, XXXXPtr). COM из C ++ поначалу сложен, поэтому в идеальном мире я бы предложил ознакомиться с основами COM, прежде чем идти слишком далеко вперед.

Однако, если вы просто хотите, чтобы что-то работало, я бы угадал это версия 101B * -стиля-COM-клиентов, которую вы предоставили:

_variant_t example1Var;
_variant_t example1Var;
SIMUL8::S8SimObjectQIPtr example1; // I'm guessing at this type-name from the VB code
SIMUL8::S8SimObjectQIPtr example2;

example1Var = pis8->GetSimObject(_bstr_t(L"Example 1"));
example2Var = pis8->GetSimObject(_bstr_t(L"Example 2"));
if (example1Var.vt == VT_DISPATCH && example2Var.vt == VT_DISPATCH)
{
   // **UPDATE** to try to spoon feed the QI ptr...
   example1 = IDispatchPtr((IDispatch*)example1Var);
   example2 = IDispatchPtr((IDispatch*)example2Var);
   // Does this screw-up reference counting?

   int numberOfexamples = example1->CountContents + example2->CountContents;

}

UPDATE:
Документация по #import Это значительно упрощает использование COM из C ++, но еще одна вещь для изучения ...

2 голосов
/ 03 марта 2009

Посмотрите документы MSDN для _variant_t

Существует метод ChangeType , а также Экстракторы .

Редактировать: Если у вас есть указатель IDispatch, вам нужно использовать <a href="http://msdn.microsoft.com/en-us/library/ms682521.aspx" rel="nofollow noreferrer">QueryInterface</a>, чтобы получить конкретный тип объекта с членами и методами, или использовать <a href="http://msdn.microsoft.com/en-us/library/ms221479.aspx" rel="nofollow noreferrer">IDispatch::Invoke</a>. Вы можете посмотреть документы MSDN для <a href="http://msdn.microsoft.com/en-us/library/ms221608.aspx" rel="nofollow noreferrer">IDispatch</a>. В любом случае вам нужно знать о типе объекта, который возвращается вызовом IS8Simulation::GetSimObject.

Редактирование # 2: На основе вашего обновления кода VB вы хотите использовать тот же тип кода для C ++, то есть использовать тип S8SimObject в его форме C ++ (смотрите в сгенерированном .tlh файл для _COM_SMARTPTR_TYPEDEF). Тогда вы можете напрямую сделать то же самое с CountContents. В противном случае вам нужно будет найти CountContents DISPID с помощью <a href="http://msdn.microsoft.com/en-us/library/ms221306.aspx" rel="nofollow noreferrer">IDispatch::GetIDsOfNames</a> и затем вызвать invoke.

1 голос
/ 03 марта 2009

Вам не нужно конвертировать _variant_t. Он содержит указатель интерфейса IDispatch, поэтому вы можете получить его следующим образом:

if (v.vt == VT_DISPATCH)
{
    IDispatchPtr pDispatch = v.pdispVal;
    // Do something with pDispatch.
    // e.g. assign it to a strongly-typed interface pointer.
}
0 голосов
/ 03 марта 2009

Существует понятие "значение" для объекта (DISPID_VALUE).

Вот статья codeproject.com о разрешении ВАРИАНТОВ, которая может помочь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...