Я использую Scripting.Dictionary из библиотеки COM «Microsoft Scripting Runtime» (c: \ windows \ System32 \ scrrun.dll). Я использую импорт, чтобы получить мои обертки, и они работают. После добавления некоторых элементов я пытаюсь получить список ключей, но я застрял.
У меня есть какой-то способ. Я могу получить SAFEARRAY
ключей из словаря, но я хочу использовать CComSafeArray
класс, определенный в <atlsafe.h>
но я не могу понять, хорошая конструкция. В настоящее время конструктор создает ATL
утверждение жалуется на vartype
несоответствие. Следует признать, что недавно построенный CComSafeArray имеет vartype
52428 CCCC в шестнадцатеричном виде, и это выглядит потенциально как неинициализированная память. Но выведенный тип также выглядит неправильно, я ожидаю, что vartype safearray будет строками, но код подтверждения дает vartype 12, который является UI2. Очень странно.
Во всяком случае, это, вероятно, легко для тех, кто знаком с этим. Вот консольная программа Minimal, Complete, Verifiable, Example (MCVE) в соответствии со стандартами SO.
#include "stdafx.h"#include <atlbase.h>
#include <atlsafe.h>
#import "c:\windows\System32\scrrun.dll" raw_interfaces_only,raw_native_types, named_guids, rename("DeleteFile", "_DeleteFile"), rename("MoveFile","_MoveFile"), rename("CopyFile", "_CopyFile"), rename("GetFreeSpace", "_GetFreeSpace")
int main()
{
HRESULT hr = S_OK;
CoInitialize(0);
CComQIPtr<Scripting::IDictionary> dictColours;
hr = dictColours.CoCreateInstance(__uuidof(Scripting::Dictionary));
if (!SUCCEEDED(hr)) { return hr; }
CComVariant varZero(0); //dummy value, only interested in keys
hr = dictColours->Add(&variant_t(L"red"), &varZero);
if (!SUCCEEDED(hr)) { return hr; }
hr = dictColours->Add(&variant_t(L"green"), &varZero);
if (!SUCCEEDED(hr)) { return hr; }
hr = dictColours->Add(&variant_t(L"blue"), &varZero);
if (!SUCCEEDED(hr)) { return hr; }
long lColourCount(0);
hr = dictColours->get_Count(&lColourCount);
if (!SUCCEEDED(hr)) { return hr; }
CComVariant varColoursKeys;
hr = dictColours->Keys(&varColoursKeys);
if (!SUCCEEDED(hr)) { return hr; }
SAFEARRAY keys(*(varColoursKeys.parray));
//fine up to this point
CComSafeArray<VARIANT> varColours;
/* The following code throws an error for the next (line) live, vt=52428 or hex CCCC which looks like uninitialised memory
whilst GetType() returns 12 which is UI2 (and somehow I expected string type 8!)
VARTYPE vt;
HRESULT hRes = ::ATL::AtlSafeArrayGetActualVartype(const_cast<LPSAFEARRAY>(psaSrc), &vt);
ATLENSURE_SUCCEEDED(hRes);
ATLENSURE_THROW(vt == GetType(), E_INVALIDARG);
*/
varColours = (keys);
CoUninitialize();
return 0;
}
Изменить это:
SAFEARRAY keys(*(varColoursKeys.parray));
К этому:
SAFEARRAY* keys = varColoursKeys.parray;
(по желанию, сначала убедитесь, что varColoursKeys.vt
имеет VT_ARRAY
флаг)
И тогда вы можете запросить keys
для его vt
:
hr = ::ATL::AtlSafeArrayGetActualVartype(keys, &vt);
Обратите внимание, что varColours = keys
собирается сделать копия данных массива. Если это не то, что вы действительно хотите, то вам следует Detach()
массив из CComVariant
(или просто использовать VARIANT
прямо а не CComVariant
) а также Attach()
это к CComSafeArray
(тогда вы можете использовать CComSafeArray::GetType()
метод).
Кроме того, вы должны убедиться, что все ваши оболочки COM выходят за рамки и высвобождают ресурсы до ты звонишь CoUninitialize()
,
Попробуй это:
#include "stdafx.h"#include <atlbase.h>
#include <atlsafe.h>
#import "c:\windows\System32\scrrun.dll" raw_interfaces_only,raw_native_types, named_guids, rename("DeleteFile", "_DeleteFile"), rename("MoveFile","_MoveFile"), rename("CopyFile", "_CopyFile"), rename("GetFreeSpace", "_GetFreeSpace")
HRESULT DoIt()
{
CComQIPtr<Scripting::IDictionary> dictColours;
hr = dictColours.CoCreateInstance(__uuidof(Scripting::Dictionary));
if (FAILED(hr)) { return hr; }
CComVariant varZero(0); //dummy value, only interested in keys
hr = dictColours->Add(&variant_t(L"red"), &varZero);
if (FAILED(hr)) { return hr; }
hr = dictColours->Add(&variant_t(L"green"), &varZero);
if (FAILED(hr)) { return hr; }
hr = dictColours->Add(&variant_t(L"blue"), &varZero);
if (FAILED(hr)) { return hr; }
long lColourCount(0);
hr = dictColours->get_Count(&lColourCount);
if (FAILED(hr)) { return hr; }
VARIANT varColoursKeys;
hr = dictColours->Keys(&varColoursKeys);
if (FAILED(hr)) { return hr; }
CComSafeArray<VARIANT> varColours;
varColours.Attach(varColoursKeys.parray);
// use varColours as needed...
VARTYPE vt = varColours.GetType();
LONG lLower = varColours.GetLowerBound();
LONG lUpper = varColours.GetUpperBound();
for (LONG i = lLower; i <= lUpper; ++i)
{
VARIANT &v = varColours.GetAt(i);
// use v.bstrVal as needed ...
}
//...
return S_OK;
}
int main()
{
HRESULT hr = CoInitialize(0);
if (FAILED(hr)) { return hr; }
hr = DoIt();
CoUninitialize();
return hr;
}
Других решений пока нет …