-
Notifications
You must be signed in to change notification settings - Fork 107
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal: APIs to easily get the ABI for an activation factory #1325
Comments
I think a cleaner alternative design would be to expose |
More than happy to update the proposal with a different API surface if you think it'd be best! 😄 |
If the goal here is to be able to call functions for interop interfaces implemented on activation factories, I would say we should make it easier than having someone write out all the vftbl logic. Someone should be able to write out the interop interface in C# and then put an attribute like Then a developer consuming an interop function would just need to do |
I think if you're looking to be trimming/AOT friendly, then you should look at interoperating with the new |
Leaving the source generator part aside for a minute, since that's not available yet, isn't this already doable today? Eg: var activationFactoryNative = CanvasDevice.As<ICanvasFactoryNative>();
[Guid("695C440D-04B3-4EDD-BFD9-63E51E9F7202")]
[WindowsRuntimeType]
[WindowsRuntimeHelperType(typeof(ICanvasFactoryNative))]
public interface ICanvasFactoryNative
{
[Guid("695C440D-04B3-4EDD-BFD9-63E51E9F7202")]
public unsafe struct Vftbl
{
public static readonly IntPtr AbiToProjectionVftablePtr = InitVtbl();
private static IntPtr InitVtbl()
{
Vftbl* lpVtbl = (Vftbl*)ComWrappersSupport.AllocateVtableMemory(typeof(Vftbl), sizeof(Vftbl));
lpVtbl->IUnknownVftbl = IInspectable.Vftbl.AbiToProjectionVftable;
return (IntPtr)lpVtbl;
}
private IInspectable.Vftbl IUnknownVftbl;
}
} That is, One point that isn't covered though is
This sounds great, and just relying on those would seem the best path forwards. Should we open a different issue to track what changes and/or new APIs would be needed from either .NET or CsWinRT to properly bridge that gap between the two? |
@jlaanstra do you think this could fit into the work you're doing around activation factories? The current pattern is very clunky and quite inefficient, as you need to declare your own dummy interface and vtable, and then do CsWinRT/src/WinRT.Runtime/ObjectReference.cs Line 164 in 7116993
Especially if you don't even need a managed reference at all (which is the case if you need to get access to some interop interface), virtually all of this is just unnecessary work and lots of overhead for nothing. Could we maybe add an API like: namespace WinRT;
public static class ActivationFactory
{
public static IntPtr GetAbi(string typeName);
} Then you could just do this: using ComPtr<IUnknown> factoryUnknown = default;
factoryUnknown.Attach((IUnknown*)ActivationFactory.GetAbi("Microsoft.Graphics.Canvas.CanvasDevice"));
using ComPtr<ICanvasFactoryNative> factoryNative = default;
factoryUnknown.CopyTo(factoryNative.GetAddressOf()); And you're good to go, no extra interfaces needed, no unnecessary RCWs being allocated or anything like that. |
Let me see how this could fit in. |
Thank you! Also on a related note: could this be another argument in favor of removing all of the FYI @manodasanW |
Leaving a note here too so I don't forget. Just copy pasting from Teams basically. I was looking at the new APIs and thinking this might be doable once #1390 is merged? Basically I'm thinking, once OLD CODE IMyInterface factory = TheType.As<IMyInterface>();
*nativeType = (NativeType*)MarshalInterface<IMyInterface>.FromManaged(factory); NEW CODE using IObjectReference factory = ActivationFactory.Get("My.Type");
factory.TryAs(NativeTypeIID, out *nativeType).Assert(); For context, I need this here. I think this would work and resolve the issue, right? 🤔 |
For context, the functionality was added in #1390 🎉 using IObjectReference factory = ActivationFactory.Get("My.Type", NativeTypeIID);
IntPtr factoryNative = factory.GetRef(); We can close this once we merge the staging branch into master. |
Proposal: API to easily get the ABI for an activation factory
Summary
Currently, there is no easy way to get the ABI for a given activation factory with CsWinRT. This is a relatively common thing to need, as there are times where the activation factory also implements some interop interface that exposes some additional functionality. For instance, Win2D does this, where the activation factory for
CanvasDevice
also implements theICanvasFactoryNative
interface defined in the public header (see microsoft/Win2D#910) which then exposes several lowlevel APIs (source here).To get the ABI for an activation factory with CsWinRT today, since
ActivationFactory<T>
is internal, you need to declare a dummy interface for the activation factory, callSomeType.As<Interface>
, and then marshal that interface to get the ABI. This is not intuitive at all, unnecessarily verbose (as you need to declare one dummy interface) and also not that fast, since you need to marshal that whole managed wrapper for nothing. The proposal is about adding first-class support for just getting the ABI of some activation factory.Use case example
Compare what you currently have to do to get the ABI for
ICanvasFactoryNative
:Compared to how simple it'd be with the new APIs:
Rationale
The text was updated successfully, but these errors were encountered: