Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# IBuffer.AsStream导致无法强制转换COM对象异常_C#_Windows Phone 8_Com_Windows Runtime_C++ Cx - Fatal编程技术网

C# IBuffer.AsStream导致无法强制转换COM对象异常

C# IBuffer.AsStream导致无法强制转换COM对象异常,c#,windows-phone-8,com,windows-runtime,c++-cx,C#,Windows Phone 8,Com,Windows Runtime,C++ Cx,在我的Windows Phone 8应用程序中,我试图将后台代理程序(用c++/cx编写)中获取的数据发送到前台应用程序(用c#编写)。我可以成功地登记回调用,并调用C++中从C层编写的函数(在单独的后台进程中运行)。p> 我的C#函数是 public virtual void OnNewAudioData(IBuffer buffer) { byte[] data = new byte[buffer.Length]; var reader = buffer.AsStream()

在我的Windows Phone 8应用程序中,我试图将后台代理程序(用c++/cx编写)中获取的数据发送到前台应用程序(用c#编写)。我可以成功地登记回调用,并调用C++中从C层编写的函数(在单独的后台进程中运行)。p> 我的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 _消息=无法将类型为“System.\u ComObject”的COM对象强制转换为接口类型“System.Runtime.InteropServices.WindowsRuntime.IBufferByteAccess”。此操作失败,因为对IID为“{905A0FEF-BC53-11DF-8C49-001E4FC686DA}”的接口的COM组件的QueryInterface调用由于以下错误而失败:不支持此类接口(HRESULT的异常:0x80004002(E_NOINTERFACE))

[编辑:添加更多代码]

我调用C#回调的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));
}
void BackEndTransport::Write(字节*字节,整数字节计数)
{
ComPtr spNativeBuffer=NULL;
MakeAndInitialize(&spNativeBuffer,bytes,byteCount,FALSE);
//调用对C#layer的回调
Globals::Instance->CallController->OnNewAudioData(NativeBuffer::GetIBufferFromNativeBuffer(spNativeBuffer));
}
NativeBuffer类的实现如下(取自示例)

#pragma一次
#包括“windows.h”
#包括
#包括
#包括
#包括
#包括
名称空间PhoneVoIPApp
{
命名空间后端
{
/// 
///此类的目的是将字节缓冲区转换为IBuffer
/// 
类NativeBuffer:公共Microsoft::WRL::RuntimeClass<
Microsoft::WRL::RuntimeClassFlags,
ABI::Windows::Storage::Streams::IBuffer,
Windows::Storage::Streams::iBufferByte访问,
Microsoft::WRL::FtmBase>
{
公众:
虚拟~NativeBuffer()
{
if(m_pBuffer和m_bIsOwner)
{
删除[]m_pBuffer;
m_pBuffer=NULL;
}
}
STDMETHODIMP运行时分类初始化(UINT totalSize)
{
m_长度=总尺寸;
m_uFullSize=总尺寸;
m_pBuffer=新字节[总大小];
m_bIsOwner=真;
返回S_OK;
}
STDMETHODIMP RuntimeClassInitialize(字节*pBuffer,UINT totalSize,BOOL ftakeOwnershipFPassedinBuffer)
{
m_长度=总尺寸;
m_uFullSize=总尺寸;
m_pBuffer=pBuffer;
m_bIsOwner=FTAKeownershipFPassedinbuffer;
返回S_OK;
}
STDMETHODIMP缓冲区(字节**值)
{
*值=m_pBuffer;
返回S_OK;
}
STDMETHODIMP获取容量(UINT32*值)
{
*值=m_fullsize;
返回S_OK;
}
STDMETHODIMP get_长度(UINT32*值)
{
*值=m_长度;
返回S_OK;
}
标准方法输入长度(UINT32值)
{
如果(值>m_fullSize)
{
返回E_INVALIDARG;
}
m_长度=数值;
返回S_OK;
}
静态Windows::Storage::Streams::IBuffer^GetIBufferFromNativeBuffer(Microsoft::WRL::ComPtr spNativeBuffer)
{
auto iinspectable=重新解释强制转换(spNativeBuffer.Get());
返回重新解释(不可检测);
}
静态字节*GetBytesFromIBuffer(Windows::Storage::Streams::IBuffer^buffer)
{
自动iinspectable=(iinspectable*)重新解释强制转换(缓冲区);
微软::WRL::ComPtr spBuffAccess;
HRESULT hr=iinspectable->QueryInterface(u uuidof(Windows::Storage::Streams::IBufferByteAccess),(void**)和SPBufferByteAccess);
UCHAR*前置缓冲器;
spBuffAccess->Buffer(&pReadBuffer);
返回预缓冲;
}
私人:
UINT32米长;
UINT32米整尺寸;
字节*m_pBuffer;
布尔·穆比索恩;
};
}
}
[编辑2:] 根据Hans Passant的建议,我尝试修改函数GetIBufferFromNativeBuffer以使用QueryInterface而不是重新解释cast。但我还是被卡住了(我的怀疑与代码一致)

static Windows::Storage::Streams::IBuffer^GetIBufferFromNativeBuffer(Microsoft::WRL::ComPtr spNativeBuffer)
{
auto myBuffer=spNativeBuffer.Get();
IUnknown*iinspectable=重新解释强制转换(myBuffer);
微软::WRL::ComPtr spBuffer;
HRESULT hr=iinspectable->QueryInterface(u uuidof(ABI::Windows::Storage::Streams::IBuffer),(void**)和spBuffer);
//如何将ABI::Windows::Storage::Streams::IBuffer转换为Windows::Storage::Streams::IBuffer?
返回。。。。;
}

这可能是实现此缓冲区的任何代码中的错误。它违反了实现IBuffer还需要实现IBufferByteAccess的要求。我们当然看不到。@HansPassant解决方案是什么?当然要修复您的C++/CX代码。我们仍然看不到它。我用更多的代码更新了这个问题。你不能用reinterpret_cast获得接口指针。您知道如何正确执行此操作,我看到您正在使用QueryInterface()。
#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;
        };
    }
}
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 ....;
}