首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >IDis补丁::调用ty胡枝子结构的pass指针作为参数

IDis补丁::调用ty胡枝子结构的pass指针作为参数
EN

Stack Overflow用户
提问于 2017-09-15 09:31:03
回答 1查看 252关注 0票数 0

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

代码语言:javascript
复制
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:

代码语言:javascript
复制
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_USERDEFINEDVT_PTRVT_PTR VT_BYREF,并将指针设置为VARIANT::byref,不工作。

请帮帮忙。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-09-15 16:15:33

IDispatch只支持与自动化兼容的类型。在这里或多或少地描述了这个列表:

wireVARIANT

因此,有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的描述

代码语言:javascript
复制
library udttest
{
    typedef [uuid(C1D3A8C0-A4AA-11D0-819C-00A0C90FFFC3)]
    struct_tagUDT
    {
        unsigned long a1;
        BSTR pbstr;
    } UDT;
}

由于EdmRect不是UDT (它看起来不是,但我手头没有原始的tlb来确认),所以您只能使用早期绑定来调用它,类似于这样:

代码语言:javascript
复制
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对您方便的话。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/46236300

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档