我需要调用函数 GetRect ,其参数是结构 EdmRect 的指针,没有 GUID :
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 = ▭
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_PTR 和 VT_PTR | VT_BYREF 和 VT_USERDEFINED 并设置指向VARIANT :: byref的指针不起作用。
请帮忙。
答案 0 :(得分:1)
IDispatch仅支持自动化兼容类型。这里列出的列表或多或少:
所以,有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(用户定义的类型)。
通过类型库驱动传递单个UDT或UDT的安全阵列 编组用于v表绑定,C和C ++自动化客户端需要 从描述UDT的IDL生成的头文件
Visual Basic客户端需要从IDL生成的类型库 文件。但是最近要传递单个UDT或UDT的安全阵列 绑定,自动化客户端必须具有必要的信息 将UDT的类型信息存储到VARIANT中(如果存储的话) 后期绑定,UDT必须自我描述。)
这就是您描述UDT within .IDL files
的方式library udttest
{
typedef [uuid(C1D3A8C0-A4AA-11D0-819C-00A0C90FFFC3)]
struct_tagUDT
{
unsigned long a1;
BSTR pbstr;
} UDT;
}
由于EdmRect 不一个UDT(好吧,它似乎不是,但我手边没有原始的tlb来确认),你只能使用早期绑定来调用它,那样:
IEdmState7 *pState;
disp->QueryInterface(IID_IIEdmState7, (void**)&pState);
EdmRect rect;
pState->GetRect(&rect);
...
因此,您需要IEdmState7的.H头文件。如果供应商没有提供一个(恕我直言,他应该,或源.IDL),但你有一个TLB,那么所有希望都不会丢失。
一种解决方案是使用Visual Studio #import directive(每个人都可以使用社区版),保留.TLH和.TLI生成的文件并使其适应您的编译器(在这种情况下,我建议您使用raw_interfaces_only)。
另一个解决方案是使用OLE/COM Object Viewer(以管理员身份运行...)或名为OleWoo的工具,它可以替代旧版本。
它应该从.TLB创建一个.H文件。请注意,您只需要不支持IDispatch的界面,如果IDispatch对您来说很方便,则不需要整个.H文件。