我需要调用函数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_USERDEFINED和VT_PTR和VT_PTR VT_BYREF,并将指针设置为VARIANT::byref,不工作。
请帮帮忙。
发布于 2017-09-15 16:15:33
IDispatch只支持与自动化兼容的类型。在这里或多或少地描述了这个列表:
因此,有I8、I4、I2、I1、INT、UI8、UI4、UI2、UI1、UINT、R8、R4、CY、ERROR、BOOL、十进制、NULL、空、日期、BSTR、未知、分派、BYREF和SAFEARRAYs。
就这样。没有原始C结构,没有VT_PTR等。
其他VT_*是为PROPVARIANT保留的,PROPVARIANT是一种类似但完全不同的野兽,不受IDispatch支持(它适用于可闪存的兼容类型)。
因此,您可以使用C结构,但它必须在类型库(或/和注册表中)中正确定义。如果定义了它,您可以称它为自动化UDT (用户定义的类型)。
要通过类型库驱动的v表绑定封送来传递单个UDT或UDT的安全射线,C和C++自动化客户端需要从描述UDT的IDL生成的头文件 Visual客户端需要从IDL文件生成的类型库。但是,要传递单个UDT或UDT的安全射线以进行后期绑定,自动化客户端必须具有必要的信息,以便将UDT的类型信息存储到变体中(如果延迟绑定,则UDT必须是自我描述的)。
这就是你对.IDL文件中的UDT的描述
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);
...因此,您需要一个用于.H的IEdmState7头文件。如果供应商没有提供一个(IMHO,他应该提供,或者源.IDL),但是您有一个TLB,那么所有的希望都不会失去。
一种解决方案是使用Visual #导入指令 (有每个人都可以使用的社区版本),保留.TLH和.TLI生成的文件并使它们适应您的编译器(在本例中,我建议您使用仅限)。
另一种解决方案是使用OLE/COM对象查看器 (作为管理员运行)或者,一个名为OleWoo wich的工具可以很好地替代旧的工具。
它应该从.H创建一个the.TLB文件。注意,您只需要不支持IDispatch的接口,不需要整个.H文件,如果IDispatch对您方便的话。
https://stackoverflow.com/questions/46236300
复制相似问题