2012-05-09 4 views
8

Voglio implementare un Cacker WinRT C++ che avvolge un buffer char *, quindi posso usarlo con le operazioni WriteAsync/ReadAsync di WinRT che accettano un parametro^di IBuffer.Come avvolgere un buffer char * in un IBuffer WinRT in C++

EDIT 1 (chiarimento)

Voglio evitare la copia dei dati.

+0

Se la funzione può assumere un array anche, questo è un supplente (e forse più facile) percorso: http://stackoverflow.com/a/16645877/588476 –

risposta

9

Per lo più copiati da http://jeremiahmorrill.wordpress.com/2012/05/11/http-winrt-client-for-c/ ma adattato per avvolgere direttamente la mia byte []:

NativeBuffer.h:

#pragma once 

#include <wrl.h> 
#include <wrl/implements.h> 
#include <windows.storage.streams.h> 
#include <robuffer.h> 
#include <vector> 

// todo: namespace 

class NativeBuffer : 
    public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::RuntimeClassType::WinRtClassicComMix>, 
    ABI::Windows::Storage::Streams::IBuffer, 
    Windows::Storage::Streams::IBufferByteAccess> 
{ 
public: 
    virtual ~NativeBuffer() 
    { 
    } 

    STDMETHODIMP RuntimeClassInitialize(byte *buffer, UINT totalSize) 
    { 
     m_length = totalSize; 
     m_buffer = buffer; 

     return S_OK; 
    } 

    STDMETHODIMP Buffer(byte **value) 
    { 
     *value = m_buffer; 

     return S_OK; 
    } 

    STDMETHODIMP get_Capacity(UINT32 *value) 
    { 
     *value = m_length; 

     return S_OK; 
    } 

    STDMETHODIMP get_Length(UINT32 *value) 
    { 
     *value = m_length; 

     return S_OK; 
    } 

    STDMETHODIMP put_Length(UINT32 value) 
    { 
     m_length = value; 

     return S_OK; 
    } 

private: 
    UINT32 m_length; 
    byte *m_buffer; 
}; 

Per creare l'IBuffer:

Streams::IBuffer ^CreateNativeBuffer(LPVOID lpBuffer, DWORD nNumberOfBytes) 
{ 
    Microsoft::WRL::ComPtr<NativeBuffer> nativeBuffer; 
    Microsoft::WRL::Details::MakeAndInitialize<NativeBuffer>(&nativeBuffer, (byte *)lpBuffer, nNumberOfBytes); 
    auto iinspectable = (IInspectable *)reinterpret_cast<IInspectable *>(nativeBuffer.Get()); 
    Streams::IBuffer ^buffer = reinterpret_cast<Streams::IBuffer ^>(iinspectable); 

    return buffer; 
} 

E la chiamata a leggere i dati (lpBuffer è il byte []):

Streams::IBuffer ^buffer = CreateNativeBuffer(lpBuffer, nNumberOfbytes); 
create_task(randomAccessStream->ReadAsync(buffer, (unsigned int)nNumberOfBytesToRead, Streams::InputStreamOptions::None)).wait(); 

Non sono così sicuro che il ComPtr abbia bisogno di una pulitura, quindi qualsiasi suggerimento riguardante la gestione della memoria è ben accetto.

+0

'm_buffer = new byte [totalSize]; 'Vedo un' new'; Non vedo alcun 'delete'. Sarebbe bene avvolgere questo in modo che quando il buffer sottostante viene distrutto, i tentativi futuri di accedervi tramite 'NativeBuffer' non funzionino (il modo in cui farlo dipende da come viene usato). Il 'reinterpret_cast' di' nativeBuffer.Get() 'a' IInspectable * 'non dovrebbe essere necessario. –

+0

Sì, mi dispiace, quella parte non avrebbe dovuto essere lì. Ho aggiornato la risposta per riflettere questo, usando il costruttore COM per impostare il byte [] come avrebbe dovuto essere. – pfo

+0

proverò questa soluzione quando ho trovato un po 'di tempo, grazie. –

5

Questo dovrebbe funzionare:

// Windows::Storage::Streams::DataWriter 
// Windows::Storage::Streams::IBuffer 
// BYTE = unsigned char (could be char too) 
BYTE input[1024] {}; 

DataWriter ^writer = ref new DataWriter(); 
writer->WriteBytes(Platform::ArrayReference<BYTE>(input, sizeof(input)); 
IBuffer ^buffer = writer->DetachBuffer(); 
Problemi correlati