IBuffer.AsStream导致无法转换COM对象异常

时间:2014-05-29 07:06:14

标签: c# windows-phone-8 com windows-runtime c++-cx

在我的Windows Phone 8应用程序中,我试图将后台代理(用c ++ / cx编写)中获得的数据发送到前台应用程序(用c#编写)。我可以成功注册一个Call back并从C ++层调用用C#编写的函数(它在不同的后台进程中运行)。

我的C#功能是

public virtual void OnNewAudioData(IBuffer buffer)
{
    byte[] data = new byte[buffer.Length];
    var reader = buffer.AsStream();
    reader.Read(data, 0, (int)buffer.Length);
}

但该函数在第二行(当我使用buffer.AsStream方法时)中断,但有以下异常

  

发生了System.InvalidCastException     _HResult = -2147467262     _message =无法转换类型为' System .__ ComObject'的COM对象。 to interface type' System.Runtime.InteropServices.WindowsRuntime.IBufferByteAccess'。此操作失败,因为QueryInterface调用COM组件上的接口与IID' {905A0FEF-BC53-11DF-8C49-001E4FC686DA}'由于以下错误而失败:不支持此类接口(HRESULT异常:0x80004002(E_NOINTERFACE))。

[编辑:添加更多代码]

调用C#回调的My C ++ / CX函数是

void BackEndTransport::Write(BYTE* bytes, int byteCount)
{
    ComPtr<NativeBuffer> spNativeBuffer = NULL;
    MakeAndInitialize<NativeBuffer>(&spNativeBuffer, bytes, byteCount, FALSE);

    //Invoking the call back to C# layer
    Globals::Instance->CallController->OnNewAudioData(NativeBuffer::GetIBufferFromNativeBuffer(spNativeBuffer));
}

NativeBuffer类的实现如下(取自Microsoft code样本)

#pragma once
#include "windows.h"
#include <robuffer.h>
#include <wrl.h>
#include <wrl/implements.h>
#include <wrl\client.h>
#include <windows.storage.streams.h>

namespace PhoneVoIPApp
{
    namespace BackEnd
    {
        /// <summary>
        /// The purpose of this class is to transform byte buffers into an IBuffer
        /// </summary>
        class NativeBuffer : public Microsoft::WRL::RuntimeClass<
            Microsoft::WRL::RuntimeClassFlags< Microsoft::WRL::RuntimeClassType::WinRtClassicComMix >,
            ABI::Windows::Storage::Streams::IBuffer,
            Windows::Storage::Streams::IBufferByteAccess,
            Microsoft::WRL::FtmBase>
        {

        public:
            virtual ~NativeBuffer()
            {
                if (m_pBuffer && m_bIsOwner)
                {
                    delete[] m_pBuffer;
                    m_pBuffer = NULL;
                }
            }

            STDMETHODIMP RuntimeClassInitialize(UINT totalSize)
            {
                m_uLength = totalSize;
                m_uFullSize = totalSize;
                m_pBuffer = new BYTE[totalSize];
                m_bIsOwner = TRUE;
                return S_OK;
            }

            STDMETHODIMP RuntimeClassInitialize(BYTE* pBuffer, UINT totalSize, BOOL fTakeOwnershipOfPassedInBuffer)
            {
                m_uLength = totalSize;
                m_uFullSize = totalSize;
                m_pBuffer = pBuffer;
                m_bIsOwner = fTakeOwnershipOfPassedInBuffer;
                return S_OK;
            }

            STDMETHODIMP Buffer( BYTE **value)
            {
                *value = m_pBuffer;
                return S_OK;
            }

            STDMETHODIMP get_Capacity(UINT32 *value)
            {
                *value = m_uFullSize;
                return S_OK;
            }

            STDMETHODIMP get_Length(UINT32 *value)
            {
                *value = m_uLength;
                return S_OK;
            }

            STDMETHODIMP put_Length(UINT32 value)
            {
                if(value > m_uFullSize)
                {
                    return E_INVALIDARG;
                }
                m_uLength = value;
                return S_OK;
            }

            static Windows::Storage::Streams::IBuffer^ GetIBufferFromNativeBuffer(Microsoft::WRL::ComPtr<NativeBuffer> spNativeBuffer)
            {
                auto iinspectable = reinterpret_cast<IInspectable*>(spNativeBuffer.Get());
                return reinterpret_cast<Windows::Storage::Streams::IBuffer^>(iinspectable);
            }
            static BYTE* GetBytesFromIBuffer(Windows::Storage::Streams::IBuffer^ buffer)
            {
                auto iinspectable = (IInspectable*)reinterpret_cast<IInspectable*>(buffer);
                Microsoft::WRL::ComPtr<Windows::Storage::Streams::IBufferByteAccess> spBuffAccess;
                HRESULT hr = iinspectable->QueryInterface(__uuidof(Windows::Storage::Streams::IBufferByteAccess), (void **)&spBuffAccess);
                UCHAR * pReadBuffer;
                spBuffAccess->Buffer(&pReadBuffer);
                return pReadBuffer;
            }
        private:
            UINT32 m_uLength;
            UINT32 m_uFullSize;
            BYTE* m_pBuffer;
            BOOL m_bIsOwner;
        };
    }
}

[编辑2:] 根据Hans Passant的建议,我尝试修改函数 GetIBufferFromNativeBuffer 以使用 QueryInterface 而不是reinterpret_cast。但我仍然被困住(我的疑问与代码一致)。

static Windows::Storage::Streams::IBuffer^ GetIBufferFromNativeBuffer(Microsoft::WRL::ComPtr<NativeBuffer> spNativeBuffer)
{
    auto myBuffer = spNativeBuffer.Get();
    IUnknown* iinspectable = reinterpret_cast<IUnknown*>(myBuffer);

    Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBuffer> spBuffer;
    HRESULT hr = iinspectable->QueryInterface(__uuidof(ABI::Windows::Storage::Streams::IBuffer), (void **) &spBuffer);

    //How can I convert ABI::Windows::Storage::Streams::IBuffer to Windows::Storage::Streams::IBuffer?
    return ....;
}

0 个答案:

没有答案