- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我正在使用 COM 库“Microsoft 脚本运行时”(c:\windows\System32\scrrun.dll) 中的 Scripting.Dictionary。我正在使用 import 来获取我的包装器,它们正在工作。添加一些项目后,我试图获取键列表,但我被卡住了。
我有办法。我可以得到 SAFEARRAY
字典中的键,但我想使用 CComSafeArray
<atlsafe.h>
中定义的类但我想不出一个好的结构。目前,构造函数抛出 ATL
。断言提示vartype
不匹配。诚然,新建的 CComSafeArray 有一个 vartype
CCCC 的 52428(十六进制),这看起来可能像未初始化的内存。但是推断的类型看起来也不正确,我希望 safearray 的 vartype 是字符串,但断言代码给出 vartype 12,即 UI2。很奇怪。
无论如何,对于熟悉此内容的人来说,这可能很容易。这是一个符合 SO 标准的控制台程序最小、完整、可验证、示例 (MCVE)。
#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
将制作数组数据的拷贝。如果这不是您真正想要的,那么您应该从 CComVariant
中Detach()
数组(或者直接使用 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;
}
关于c++ - 如何初始化从 Scripting.Dictionary Keys 方法返回的 SAFEARRAY CComSafeArray,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49619401/
我有一个 Com 函数: GetData (SAFEARRAY ** pRetVal) 我有以下代码: SAFEARRAY *ppData = NULL; hr = pmyInterfac
我使用以下语句创建了包含 32 个元素的 CComSafeArray 对象。但经过一些操作后,我才知道我只需要安全数组中的 3 个元素。是否可以在创建安全数组后更改其中元素的数量? CComSafeA
我有一个 COM 函数: GetData(SAFEARRAY ** pRetVal) 和以下遗留代码: CComSafeArray saDataArray; hr = pmyInterface->Ge
我的情况是我有一个 COM 对象,我需要在 come windows 中仅使用 C++ 代码。 COM 对象具有接受 SAFEARRAY 作为参数以传递字节数组的函数。在查看了 SAFEARRAY A
CComSafeArray::SetAt method提供一个参数来控制引用的变量是否被复制: HRESULT SetAt( LONG lIndex, const T& t, BOOL bCopy =
我尝试了 GetSafeArrayPtr() 方法,该方法返回一个 LPSAFEARRAY*,typedef 定义为: typedef /* [wire_marshal] */ SAFEARRAY *
我有一个内存泄漏问题,我已将其缩小到以下代码。怎么回事? CComSafeArray sa(5); sa[0] = SysAllocString("constant"); CComSafeArray:
CComSafeArray arr; arr.Add(0x00); 错误 -> C2668:“ATL::CComSafeArray::Add”:对重载函数的调用不明确 我可以添加任何值但不能添加 0
我正在尝试 (i) 跨 COM 边界获取长整型安全数组,以及 (ii) 为方便起见使用 CComSafeArray。 我的问题是在设置 COM 属性后我遇到了不可预测的崩溃(参见下面的 pProlog
我有一个应该通过 LPSAFEARRAY* 返回 SafeArray 的 COM 函数出参数。该函数使用 ATL 的 CComSafeArray 创建 SafeArray模板类。我天真的实现使用 CC
这很可能有一个非常简单的答案,但我无法弄清楚。 我正在尝试重构一些如下所示的代码: SAFEARRAY* psa; long* count; HRESULT hr = pSomeInterface->
有什么快速的方法可以将 std::vector 转换为 CComSafeArray。我目前正在编写一段代码,基本上将 5 或 6 vector 转换为 CComSafeArray(不是在迭代中)。其中
我正在使用 ATL CComSafeArray类,但是如果数组为空,GetCount() 似乎会抛出异常,例如这段代码抛出异常: CComSafeArray array; // array.Add(i
在MSDN documentation for CComSafeArray::MultiDimSetAt , alIndex 记录如下: Pointer to a vector of indexes
我正在使用 COM 库“Microsoft 脚本运行时”(c:\windows\System32\scrrun.dll) 中的 Scripting.Dictionary。我正在使用 import 来获
CComSafeArray fields; hr = _tab_file->get_Fields(fields.GetSafeArrayPtr()); for ( LONG i = fields.Ge
我是一名优秀的程序员,十分优秀!