12

I've written the following extension method to concatenate two IBuffer objects in a Windows Runtime application:

public static IBuffer Concat(this IBuffer buffer1, IBuffer buffer2)
{
    var capacity = (int) (buffer1.Length + buffer2.Length);
    var result = WindowsRuntimeBuffer.Create(capacity);
    buffer1.CopyTo(result);
    buffer2.CopyTo(0, result, buffer1.Length, buffer2.Length);
    return result;
}

Is this the most efficient way to handle this? Is there a better or easier way?

I've reviewed Best way to combine two or more byte arrays in C# but I don't think I should be converting to and from byte arrays.

Community
  • 1
  • 1
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575

1 Answers1

3

According to MSDN:

When you implement the IBuffer interface, you must implement the IBufferByteAccess interface, which is a COM interface for accessing the buffer directly. C++ callers use this interface to avoid making a copy of the buffer.

IBufferByteAccess has the following method:

HRESULT Buffer(
  [out]  byte **value
);

If you write in C++, you may use this interface to facilitate implementing data copying efficiently. However, class System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBufferExtensions, which you used in your method, is implemented in native code as well, thus it almost certanly takes advantage of the IBufferByteAccess interface. Calling method WindowsRuntimeBufferExtensions.CopyTo from managed code should be as fast as implementing its equivalent in native code and calling that implementation (unless a customized implementation would do less validation).

Roman Boiko
  • 3,576
  • 1
  • 25
  • 41
  • For those interested in investigating similar questions (related to implementation aspects of WinRT), it might be worth taking a look at http://stackoverflow.com/a/13240181/118478. – Roman Boiko Dec 19 '12 at 10:06
  • Ok, but ultimately a buffer is still a byte array? Or is it more like a stream? Is it a value type sitting on the stack, or a heap object that has to be managed? The docs are abysmal in this area! – Matt Johnson-Pint Dec 19 '12 at 14:19
  • 1
    Here are my guesses on the subject: It is highly unlikely that it is stored on stack (because of potentially large size). It must store data as an array of bytes, otherwise pointer returned from `IBufferByteAccess::Buffer` method would be unusable. It might be located outside of managed heap, because underlying implementation is not managed. However, from the following link it looks like it is stored on managed heap (and pinned when used in native code): http://answers.flyppdevportal.com/categories/metro/csharpvb.aspx?ID=72fd199b-f191-46ca-9617-66c71954af41 – Roman Boiko Dec 19 '12 at 16:14
  • Note: implementations of this interface may vary (in future WinRT versions or if third-party code implements it), so relying on its underlying structure could be dangerous. – Roman Boiko Dec 19 '12 at 16:19
  • That link had some good information. I'm still shocked and dismayed by the lack of good information about such a low-level public interface. I ran into it while being forced to convert to the new Windows.System.Cryptography mechanisms. Lots of things take an IBuffer, and you're left clueless as to how you should be handling things. If you want the bounty, see if you can find something more official on Windows Runtime Buffers in the docs or a MS blog or something with more detail. Thanks. – Matt Johnson-Pint Dec 19 '12 at 18:28
  • @Matt, bounties are not my motivation to participate on SO. I answer only those questions which I find interesting myself, and yours was. – Roman Boiko Dec 19 '12 at 18:33
  • Just revisiting this and reading the link you posted. Do you think it would be possible to just link the two buffers' memory locations rather than copy anything at all? – Matt Johnson-Pint Feb 26 '13 at 18:05
  • You mean for a custom implementation? Probably yes, for a small run-time accessing cost. – Roman Boiko Feb 27 '13 at 11:19