Sadly, this means C++/CX is unsuitable since it does not support mixed WinRT/COM classes. The most straight forward way to use private interfaces is therefore to switch to WRL instead.
Even better, you can consume and author these private interfaces in the .NET projection of WinRT, thanks to the very good COM interop support in the CLR.
All you need to do is to make sure the method order and signatures match, and that the interface declarations have the same IID. Let's see how, using the IBufferByteAccess interface on the C++ side (this is from robuffer.h):
[uuid(905a0fef-bc53-11df-8c49-001e4fc686da)]
struct IBufferByteAccess : public IUnknown
{
STDMETHOD(Buffer)(_Outptr_result_buffer_(_Inexpressible_("size given by different API")) byte **value) = 0;
};
The C# counterpart of this declaration can be:
[ComImport]
[Guid("905a0fef-bc53-11df-8c49-001e4fc686da")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IBufferByteAccess
{
void Buffer([Out] out IntPtr value);
}
You can in fact cast an IBuffer directly to this interface. No unsafe code needed.
Also interesting is that the C# method signatures are somewhat flexible. The following is also valid:
[ComImport]
[Guid("905a0fef-bc53-11df-8c49-001e4fc686da")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IBufferByteAccess
{
IntPtr Buffer { get; }
}
In fact, looking at Microsofts own System.Runtime.InteropServices.WindowsRuntime.WindowsRuntimeBuffer class in DotPeek shows that they use this form.
Now, why does this even work? Not sure, but I suspect it's NOT to do with the COM interop functionality being clever - since there IS no metadata beyond the GUID here. No TLB or winmd is involved. Rather, I think it's because such a property getter has the exact same signature as the Buffer method with an [Out] parameter does.