在我的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 ....;
}