如何构建指向 VARIANT 的指针的 SAFEARRAY?
我正在尝试通过以下方法使用 COM 组件:
HRESULT _stdcall Run(
[in] SAFEARRAY(BSTR) paramNames,
[in] SAFEARRAY(VARIANT *) paramValues
);
How can I create in C/C++ the paramValues array?
I'm trying to use a COM component with the following method:
HRESULT _stdcall Run(
[in] SAFEARRAY(BSTR) paramNames,
[in] SAFEARRAY(VARIANT *) paramValues
);
How can I create in C/C++ the paramValues array?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
添加以上答案以供未来读者参考:
在 IDL 中,
SAFEARRAY(...)
表示指向数组描述符的指针。但在 C++ 中,
SAFEARRAY
表示数组描述符。因此,IDL 的
SAFEARRAY(...)
实际上是 C++ 的SAFEARRAY *
。这让我困惑不已。更有趣的是,VB 总是通过引用传递数组。所以VB的
() As Long
是SAFEARRAY; **
在 C++ 中。 (我不知道是否真的有一个常用的标头允许您将类型指定为模板参数,但为了清楚起见我插入了它。)Adding to the answers above for reference by future readers:
In IDL,
SAFEARRAY(...)
means a pointer to an array descriptor.But in C++,
SAFEARRAY
means an array descriptor.So IDL's
SAFEARRAY(...)
is really C++'sSAFEARRAY *
. This confused me to no end.To make things even more interesting, VB always passes arrays by reference. So VB's
() As Long
isSAFEARRAY<int32_t> **
in C++. (I don't know if there actually is a commonly used header that allows you to specify the type as a template parameter, but I inserted it for clarity.)SAFEARRAY(VARIANT *) 的定义不太正确。它在 IDL 中声明为 SAFEARRAY(VARIANT),但可通过锁定 SAFEARRAY 获得的指针实际上是 VARIANT *。如果你想一下这一点,它应该更有意义。 SAFEARRAY(pvData 成员)的索引指针不可能在其物理位置中容纳整个 VARIANT,因此至少它应该能够存储可用于索引 VARIANT 数组的指针。
如果您查看,大约第 1110 行以上的某个位置您将看到 VT_ 枚举定义。那里还表明 VT_VARIANT 实际上意味着 VARIANT *。同样方便的是 [S] 标签,用于记录 SAFEARRAY 中可能出现的项目。
这是头文件副本的链接。
DOC.DDART.NET 上的 wtypes.h
从这里开始,您只需声明一个具有 VT_VARIANT 变体类型的 SAFEARRAY,然后在锁定数组时将 pvData 视为 VARIANT * 。下面是示例 win32 控制台应用程序的源代码,它通过调用与您的函数相同的声明匹配的函数来演示这一点。
可以通过创建 ATL dll 项目并添加一个名为“TestReader”的简单 ATL 对象来创建此测试应用程序调用的组件。
这是 ITestReader 的 IDL。
与 IDL 声明相对应的成员函数仅采用 SAFEARRAY *(或 LPSAFEARRAY)参数。
这是该方法的主体。为了简洁起见,还包括一个辅助函数 PrintVariant()。
The definition SAFEARRAY(VARIANT *) is not quite correct. It is declared in an IDL as SAFEARRAY(VARIANT), but the pointer available from locking the SAFEARRAY is actually a VARIANT *. If you think about this for a moment, it should make some more sense. The index pointer of a SAFEARRAY (the pvData member) can't possibly fit an entire VARIANT in its physical location, so at the very least, it should be able to store a pointer that may be used to index into an array of VARIANTs.
If you look at <wtypes.h>, somewhere about line 1110+ you'll see the VT_ enumeration definitions. It is also shown there that VT_VARIANT actually implies VARIANT *. Also handy are the [S] tags noting what items may appear in a SAFEARRAY.
Here's a link to a copy of the header file.
wtypes.h at DOC.DDART.NET
Proceeding from here, you would simply declare a SAFEARRAY with a variant type of VT_VARIANT, then treat pvData as VARIANT * when locking the array. Here is the source code for a sample win32 console app that demonstrates this by calling a function matching the same declaration as your function.
The component called by this test app can be created by creating an ATL dll project, and adding a simple ATL object called 'TestReader'.
Here's the IDL for ITestReader.
The member function corresponding to the IDL declaration just takes SAFEARRAY * (or LPSAFEARRAY) arguments.
Here is the body of the method. Also included is a helper function PrintVariant() for brevity.