gpt4 book ai didi

c - IDispatch::Invoke 将 typedef 结构的指针作为参数传递

转载 作者:行者123 更新时间:2023-11-30 14:55:05 25 4
gpt4 key购买 nike

我需要调用函数GetRect,其参数是没有GUID的结构EdmRect的指针:

typedef struct tagEdmRect {
long mlLeft;
long mlTop;
long mlRight;
long mlBottom;
} EdmRect;

[
odl,
uuid(60F6AEB0-7AEA-49F5-A4EF-DCBB1F2E6284),
helpstring("IEdmState7 Interface"),
dual,
oleautomation
]
interface IEdmState7 : IEdmState6 {
[id(0x0000000e), helpstring("GetRect")]
HRESULT GetRect([out] EdmRect* poRect);
};

请告诉我如何做正确?

现在我无法这样做,因为总是收到 E_INVALIDARG

首先我尝试使用VT_RECORD作为VARTYPE:

GUID LIBID_RecInf1Lib = { 0x5fa2c692, 0x8393, 0x4f31, { 0x9b, 0xdb, 0x05, 0xe6, 0xf8, 0x07, 0xd0, 0xd3 } };

ITypeLib* typeLib = nullptr;
hRes = LoadRegTypeLib(LIBID_RecInf1Lib, 5, 17, LOCALE_SYSTEM_DEFAULT, &typeLib);
if (FAILED(hRes))
_com_issue_error(hRes);

uint typeCount = typeLib->GetTypeInfoCount();
for (uint i = 0; i < typeCount; ++i)
{
BSTR name;
typeLib->GetDocumentation(i, &name, NULL, NULL, NULL);

if (wcscmp(name, L"EdmRect") == 0)
{
ITypeInfo* typeInfo = nullptr;
hRes = typeLib->GetTypeInfo(i, &typeInfo);
if (FAILED(hRes))
_com_issue_error(hRes);

IRecordInfo* erRecInfo = nullptr;
hRes = GetRecordInfoFromTypeInfo(typeInfo, &erRecInfo);
qDebug() << erRecInfo;
if (FAILED(hRes))
_com_issue_error(hRes);

EdmRect rect = { 0 };

VARIANTARG* v = new VARIANTARG[1];
VariantInit(&v[0]);
v[0].vt = VT_RECORD;
v[0].pvRecord = &rect;
v[0].pRecInfo = erRecInfo;

DISPPARAMS i_params = {v, NULL, 1, 0};

auto func_id = dispIDofName("GetRect", disp); // This line correct
hRes = disp->Invoke(func_id, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_METHOD, &i_params, NULL, NULL, NULL);
if (FAILED(hRes))
_com_issue_error(hRes);

break;
}
}

但是函数GetRecordInfoFromTypeInfo返回E_INVALIDARG

我还尝试使用VT_PTRVT_PTR | VT_BYREFVT_USERDEFINED 并将指针设置为 VARIANT::byref 不起作用。

请帮忙。

最佳答案

IDispatch 仅支持自动化兼容类型。该列表或多或少地描述如下:

2.2.29.1 _wireVARIANT

所以,有 I8、I4、I2、I1、INT、UI8、UI4、UI2、UI1、UINT、R8、R4、CY、ERROR、BOOL、DECIMAL、NULL、EMPTY、DATE、BSTR、UNKNOWN、DISPATCH 、所有这些的 BYREF 和 SAFEARRAY 以及 RECORD(这是历史上最新添加的)。

就是这样。没有原始 C 结构,没有 VT_PTR 等。

其他 VT_* 保留给 PROPVARIANT,它是一个类似但完全不同的野兽,不受 IDispatch 支持(它适用于 blittable 兼容类型)。

因此,您可以使用C结构,但它必须在类型库(或/和注册表)中正确定义。如果已定义,您可以将其称为 Automation UDT (用户定义类型)。

To pass single UDTs or safearrays of UDTs through type-library driven marshaling for v-table binding, C and C++ Automation clients need the header file generated from the IDL that describes the UDT

Visual Basic clients require the type library generated from the IDL file. However to pass single UDTs or safearrays of UDTs for late binding, the Automation client must have the information necessary to store the type information of the UDT into a VARIANT (and if late-binding, the UDT must be self-described).

这就是你的描述UDT within .IDL files

library udttest
{
typedef [uuid(C1D3A8C0-A4AA-11D0-819C-00A0C90FFFC3)]
struct_tagUDT
{
unsigned long a1;
BSTR pbstr;
} UDT;
}

由于 EdmRect 不是 UDT(嗯,看来不是,但我手头没有原始的 tlb 来确认),你只能使用早期绑定(bind)来调用它,像这样:

IEdmState7 *pState;
disp->QueryInterface(IID_IIEdmState7, (void**)&pState);
EdmRect rect;
pState->GetRect(&rect);
...

因此您需要 IEdmState7 的 .H 头文件。如果供应商没有提供 TLB(恕我直言,他应该,或者源 .IDL),但您有 TLB,那么一切希望都不会破灭。

一种解决方案是使用 Visual Studio #import directive (有每个人都可以使用的社区版本),保留 .TLH 和 .TLI 生成的文件并将它们适应您的编译器(在这种情况下,我建议您使用 raw_interfaces_only )。

另一个解决方案是使用OLE/COM Object Viewer (以管理员身份运行...)或名为 OleWoo 的工具这是旧版本的一个很好的替代品。

它应该从 .TLB 创建一个 .H 文件。请注意,如果 IDispatch 对您方便,您只需要不支持 IDispatch 的接口(interface),不需要整个 .H 文件。

关于c - IDispatch::Invoke 将 typedef 结构的指针作为参数传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46236300/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com