locked
How can I return byte array from winrt component written in WRL

    Question

  • I'm writing a MFT and I need to return a byte array from it. So I define a method in idl like:

    HRESULT GetOutput([out] unsigned long* lsize,[out,retval,size_is(,*lsize)] BYTE** buffer);

    and implement it:

    HRESULT CA::GetOutput(unsigned long* lsize, BYTE** buffer)
    {
    	*lsize = 5;
    	*buffer = new BYTE[5];
    	return S_OK;
    }

    So I can call it from C# project:

    byte[] data = args.GetOutput();

    But when I run the code, I got a System.AccessViolationException when assign the return value to data. How can I fix it?

        


    • Edited by tw9632 Friday, February 01, 2013 3:34 AM
    Friday, February 01, 2013 3:33 AM

All replies

  • Hi tw9632,

    An app can pass only Windows Runtime classes across the ABI boundary. This means that arrays have to be represented as a Platform::Array or Platform::WriteOnlyArray and cannot be passed as C arrays. Depending on your needs you may be better off using a collection class instead of an array.

    Take a look at the Collections and Arrays section in Creating Windows Runtime Components in C++ ,  Array and WriteOnlyArray (C++/CX) , and Passing arrays to a Windows Runtime component .

    --Rob

    Saturday, February 02, 2013 5:37 AM
    Owner
  • Hi Rob,
    Thank you for your reply. I known I need a Platform::Array to across the ABI boundary, I just don't know how to represent it in WRL's idl file. It seems only accept C++ native types. And when compiler the code I wrote above, the generated winmd contains the method signature like:

    Platform::Array<unsigned char>^ GetOutput()

    So I think the compiler can handle the type convertion, and something else goes wrong. 
    Also I read your links and none of them covers the WRL part.
    Can you give me some more suggestions? Thanks!
    Monday, February 04, 2013 11:27 AM
  • tw9632, did you found a solution?

    Here is the IDL definition from Windows Kit:

                interface IPixelDataProvider : IInspectable
                {
                    HRESULT DetachPixelData([out] UINT32* __pixelDataSize, [out] [retval] [size_is(, *__pixelDataSize)] BYTE** pixelData);
                }
    

    This will generate byte[] DetachPixelData() in C#.

    The problem seems to be in the implementation. I get no exception if I leave __pixelDataSize and pixelData as is. DetachPixelData will then return null. As soon I set some value to pixelData I get the AccessViolationException.

    Saturday, April 20, 2013 8:22 PM
  • Hi tw9632,

    I have run into exact same problem. In my case the solution was to allocate the array that I'm returning with CoTaskMemAlloc() instead of new/malloc.

    Please take a look at memory allocation in COM: http://msdn.microsoft.com/en-us/library/windows/desktop/ff485847%28v=vs.85%29.aspx

    Hope this helps.

    --Tomasz



    Wednesday, August 07, 2013 11:10 AM