通过COM将自定义接口类型的SAFEARRAY返回给VB6

发布于 2024-10-31 20:42:30 字数 381 浏览 1 评论 0原文

是否可以将已定义的接口对象数组从 C++ COM 函数 (VC6) 返回到 VB6 客户端?我在网上搜索过,但找不到任何描述我需要做什么的内容。我见过很多传递 BSTR 和 VARIANT 类型,但我需要某种方法来实际让客户端利用我在数组内返回的接口类型。

我认为我需要做什么
- 使用 SAFEARRAY
- 使用带有 VT_UNKNOWN 类型的 SAFEARRAY,这又意味着我需要将对象作为 IUnknown 对象放入数组中。

从这里开始我就陷入困境了。是否可以在 VB6 中解释 IUnknown 类型,并以某种方式将其转换为我需要的类型?或者我是否以完全错误的方式处理这个问题......

澄清:
放置在集合中的接口用于模仿结构。我本质上需要传回一个结构数组。

Is it possible to return an array of defined interface objects from a C++ COM function (VC6) to a VB6 client? I've scoured the web and haven't been able to come across anything that describes what I need to do. I've seen a lot of passing BSTR and VARIANT types, but I need some way to actually have the client side utilise the interface type that I return inside the array.

What I assume I'll need to do
- Use a SAFEARRAY
- Use the SAFEARRAY with the VT_UNKNOWN type, which in turns means I need to place the objects into the array as IUnknown objects.

From here on in I'm stumped. Is it possible to interpret an IUnknown type in VB6, and somehow turn it into the type that I require? Or am I going about this in the complete wrong way...

Clarification:
The interfaces being placed in the collection are being used to mimic a struct. I essentially need to pass back an array of structs.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

卸妝后依然美 2024-11-07 20:42:30

我提出了一个适合我的目的的解决方案,尽管不完全是我在问题中提出的。

我的解决方案是创建一个 COM 函数,该函数采用 SAFEARRAY 作为参数并修改它,而不是返回创建的数组。 VB6 客户端实例化该数组,并将其传递给 C++ 进行填充。我设想未来的使用将包括一个前体函数,VB6 调用该函数来确定所需的数组大小。作为参考,以下是代码片段:

接口函数:

[id(4), helpstring("method PopulateWithStruct")] HRESULT PopulateWithStruct([in,out]SAFEARRAY (IReturnStruct*)*ppArray, [out,retval] long*plResult);

其中 IReturnStruct 是一个包含属性值的接口,充当结构体:

interface IReturnStruct : IDispatch
{
    [propget, id(1), helpstring("property num1")] HRESULT num1([out, retval] long *pVal);
    [propget, id(2), helpstring("property str1")] HRESULT str1([out, retval] BSTR *pVal);
};

由 ReturnStruct 实现

[
    uuid(843870D0-E3B3-4123-82B4-74DE514C33C9),
    helpstring("ReturnStruct Class")
]
coclass ReturnStruct
{
    [default] interface IReturnStruct;
};

PopulateWithStruct 具有以下定义:

STDMETHODIMP CCTestInterface::PopulateWithStruct(SAFEARRAY **ppArray, long *plResult)
{
    long lLowerBound = -1;
    long lUpperBound = -1;
    SafeArrayGetLBound(*ppArray, 1, &lLowerBound);
    SafeArrayGetUBound(*ppArray, 1, &lUpperBound);

    long lArraySize = lUpperBound - lLowerBound;

    VARTYPE type;
    SafeArrayGetVartype(*ppArray, &type);

    if (lArraySize > 0)
    {
        for ( int i = lLowerBound; i < lUpperBound; ++i)
        {
            CComPtr<CReturnStruct> pRetStruct;
            HRESULT hr = CoCreateInstance(__uuidof(ReturnStruct), NULL, CLSCTX_ALL, __uuidof(IUnknown), reinterpret_cast<void **>(&pRetStruct));
            if (SUCCEEDED(hr))
            {
                pRetStruct->Initialise();
                hr = SafeArrayPutElement(*ppArray, (long*)&i, pRetStruct);
                if (FAILED(hr))
                {
                    return hr;
                }
                pRetStruct.Release();
            }
        }
        SafeArrayUnaccessData(*ppArray);
    }

    *plResult = 1;

    return S_OK;
}

在 VB 方面:

Dim obj As ATL_SERVICETESTLib.CTestInterface
Set obj = New CTestInterface

Dim Result As Long
Dim RetStructs(3) As ReturnStruct

Result = obj.PopulateWithStruct(RetStructs())

对这种方法有什么评论吗?

I've come up with a solution that is suitable for my purposes, despite not being exactly what I set out in the question.

My solution was to create a COM function that takes a SAFEARRAY as a parameter and modifies it, instead of returning a created array. The VB6 client instantiates the array, and passes it to C++ for populating. I envision that future usage will include a precursor function which VB6 calls to determine the required size of the array. For reference, here's the code snippets:

Interface function:

[id(4), helpstring("method PopulateWithStruct")] HRESULT PopulateWithStruct([in,out]SAFEARRAY (IReturnStruct*)*ppArray, [out,retval] long*plResult);

Where IReturnStruct is an interface containing property values, acting as a struct:

interface IReturnStruct : IDispatch
{
    [propget, id(1), helpstring("property num1")] HRESULT num1([out, retval] long *pVal);
    [propget, id(2), helpstring("property str1")] HRESULT str1([out, retval] BSTR *pVal);
};

And is implemented by ReturnStruct

[
    uuid(843870D0-E3B3-4123-82B4-74DE514C33C9),
    helpstring("ReturnStruct Class")
]
coclass ReturnStruct
{
    [default] interface IReturnStruct;
};

PopulateWithStruct has the following definition:

STDMETHODIMP CCTestInterface::PopulateWithStruct(SAFEARRAY **ppArray, long *plResult)
{
    long lLowerBound = -1;
    long lUpperBound = -1;
    SafeArrayGetLBound(*ppArray, 1, &lLowerBound);
    SafeArrayGetUBound(*ppArray, 1, &lUpperBound);

    long lArraySize = lUpperBound - lLowerBound;

    VARTYPE type;
    SafeArrayGetVartype(*ppArray, &type);

    if (lArraySize > 0)
    {
        for ( int i = lLowerBound; i < lUpperBound; ++i)
        {
            CComPtr<CReturnStruct> pRetStruct;
            HRESULT hr = CoCreateInstance(__uuidof(ReturnStruct), NULL, CLSCTX_ALL, __uuidof(IUnknown), reinterpret_cast<void **>(&pRetStruct));
            if (SUCCEEDED(hr))
            {
                pRetStruct->Initialise();
                hr = SafeArrayPutElement(*ppArray, (long*)&i, pRetStruct);
                if (FAILED(hr))
                {
                    return hr;
                }
                pRetStruct.Release();
            }
        }
        SafeArrayUnaccessData(*ppArray);
    }

    *plResult = 1;

    return S_OK;
}

On the VB side:

Dim obj As ATL_SERVICETESTLib.CTestInterface
Set obj = New CTestInterface

Dim Result As Long
Dim RetStructs(3) As ReturnStruct

Result = obj.PopulateWithStruct(RetStructs())

Any comments on this approach?

各空 2024-11-07 20:42:30

当您将 IUnknown 分配给特定接口类型时,VB 将在幕后执行 QueryInterface,因此应该可以正常工作。

我不知道是否可以将用户定义类型的数组传递给 VB6,我在网上找到的所有文档都停留在 VS2003,但我希望这是可能的。

VB will do a QueryInterface behind the scenes when you assign the IUnknown to a particular interface type, so that should Just Work.

I don't know if you can pass an array of user-defined type to VB6, all the documentaiton I can find on the web stops at VS2003, but I would expect it would be possible.

七婞 2024-11-07 20:42:30

你可以将它包装在一个变体中,然后它就可以工作了。

idl:

[propget, id(10), helpstring("blabla")]
HRESULT MyListProp([out, retval] VARIANT *ppsaList); 

cpp:

STDMETHODIMP CAnyClass::get_MyListProp(/*[out, retval]*/ VARIANT* ppsaList)
{
HRESULT hr = S_OK;

if (ppsaList== NULL)
{
    return E_INVALIDARG;
}

CComSafeArray <IDispatch*> saVars;

// I have my objects in a list m_List that I am copying to saVars
for (std::list<IMyObj*>::iterator it = m_List.begin();
     it != m_List.end();
     ++it)
{
    IDispatch* pUnk = NULL;
    if ((*it)->QueryInterface(IID_IDispatch, (void**)&pUnk) == S_OK)
    {
        saVars.Add(pUnk);
    }
}

CComVariant varReturn (saVars.Detach());
varReturn.Detach(ppsaList);
return S_OK;
} 

vb:

Dim arr
arr = obj.MyListProp

' these will all work
ub = UBound(arr)
lb = LBound(arr)

You can wrap the thing in a variant and then it works.

idl:

[propget, id(10), helpstring("blabla")]
HRESULT MyListProp([out, retval] VARIANT *ppsaList); 

cpp:

STDMETHODIMP CAnyClass::get_MyListProp(/*[out, retval]*/ VARIANT* ppsaList)
{
HRESULT hr = S_OK;

if (ppsaList== NULL)
{
    return E_INVALIDARG;
}

CComSafeArray <IDispatch*> saVars;

// I have my objects in a list m_List that I am copying to saVars
for (std::list<IMyObj*>::iterator it = m_List.begin();
     it != m_List.end();
     ++it)
{
    IDispatch* pUnk = NULL;
    if ((*it)->QueryInterface(IID_IDispatch, (void**)&pUnk) == S_OK)
    {
        saVars.Add(pUnk);
    }
}

CComVariant varReturn (saVars.Detach());
varReturn.Detach(ppsaList);
return S_OK;
} 

vb:

Dim arr
arr = obj.MyListProp

' these will all work
ub = UBound(arr)
lb = LBound(arr)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文