-
Notifications
You must be signed in to change notification settings - Fork 199
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
Add basic implementation of the ComWrappers #653
Conversation
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
476636a
to
9c5744a
Compare
@jkotas I have future questions. Other option is to extend |
You can do that using ConditionalWeakTable, like it is done in #306 (comment). ConditionalWeakTable and SyncBlocks are equivalent mechanisms. I think we would actually prefer ConditionalWeakTable as the permanent solution for this. |
@jkotas I have what I would say very rough draft. I just trying understand do I move in proper direction or not? |
Yes, I think you are going in the right direction. I think some of the internal and private "called by the runtime" methods you have copied over will have different shape at the end or won't be needed at all. |
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
I have 2 ideas. CCW seems to be rathe rcompilcated. But RCW require just having Dictionary<IntrPtr, object> to keep track of RCWs. Most likely this should be some weekly referenced object, which should release COM object when no longer referenced. In fnalizer probably.
31f8365
to
f8165c6
Compare
@jkotas do I still move in proper direction? I definitely still have some not needed flags, and what I assume I should do if I move in right direction
Questions
|
...reclr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/GCHandle.CoreRT.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I think you are still moving in the right direction. I have left a bunch of comments.
I assume that ComInterfaceInstance is partly what is ManagedObjectWrapper. Should I use only one structure?
Yes, they look the same. It would make sense to use only one structure.
What's better way for memmove at that level?
We prefer to use Span.CopyTo
where posible instead of memmove
.
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
@jkotas I think I more or less finish with COM creation. |
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
...lr/nativeaot/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.CoreRT.cs
Outdated
Show resolved
Hide resolved
Jan is on vacation :).
This is what we discussed in #802. You can delete __BlockAllReflectionAttribute from the test to unblock yourself right now. |
src/tests/nativeaot/SmokeTests/ComWrappers/ComWrappersNative.cpp
Outdated
Show resolved
Hide resolved
@jkotas is this comments all what you have? I'm done with comments. Hope you enjoy your vacation. |
{ | ||
if (pUnk == null) | ||
{ | ||
return IntPtr.Zero; | ||
} | ||
|
||
#if TARGET_WINDOWS | ||
#pragma warning disable CA1416 | ||
Guid interfaceGuid = convertToType.GUID; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be more inline with the NativeAOT design printiples for the GUID to be passed as an argument into this method by the toolchain instead of computing it at runtime via reflection.
@MichalStrehovsky Do you expect that there are going to be special measures required to make the interface reflectable going forward, or is this going to just work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using reflection to fetch the GUID here is also going to make the marshalling much slower compared to regular CLR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the design we will have to settle with is that types are always reflectable, so fetching a GUID should be reliable, but yes, this is not going to be very fast.
It shouldn't be too much of a problem to change this signature of this helper to take an actual GUID, and in the compiler:
- Use
.GetDecodedCustomAttributes
to get the attributes on the type. - Parse the string into a GUID.
- Emit IL to call the
Guid(Int32, Int16, Int16, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte)
constructor with the parsed GUID values.
We can scope out types that don't have a GuidAttribute for now (runtime reflection would not compute the correct GUID for them either).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@MichalStrehovsky I'm not sure that I properly understand how to jump from TypeDesc
to EcmaType
.
I plan to use following
CustomAttributeValue<TypeDesc>? customAttributeValue = ((EcmaType)this.ManagedParameterType.GetTypeDefinition()).GetDecodedCustomAttribute("", "GuidAttribute");
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
(this.ManagedParameterType as EcmaType)?.GetDecodedCustomAttribute("System.Runtime.InteropServices", "GuidAttribute")
- The attribute namespace has to be specified
GetTypeDefinition
would be only needed for generic types. Built-in COM interop does not work for generic types so you can just skip that part.
Two comments left:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks great, thank you!
{ | ||
public static int Main(string[] args) | ||
{ | ||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if you put <CLRTestTargetUnsupported Condition="'$(TargetsWindows)' != 'true'">true</CLRTestTargetUnsupported>
in the csproj, this test will be skipped. It's better than AOT compiling it only for the test to do nothing.
{ | ||
if (pUnk == null) | ||
{ | ||
return IntPtr.Zero; | ||
} | ||
|
||
#if TARGET_WINDOWS | ||
#pragma warning disable CA1416 | ||
Guid interfaceGuid = convertToType.GUID; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the design we will have to settle with is that types are always reflectable, so fetching a GUID should be reliable, but yes, this is not going to be very fast.
It shouldn't be too much of a problem to change this signature of this helper to take an actual GUID, and in the compiler:
- Use
.GetDecodedCustomAttributes
to get the attributes on the type. - Parse the string into a GUID.
- Emit IL to call the
Guid(Int32, Int16, Int16, Byte, Byte, Byte, Byte, Byte, Byte, Byte, Byte)
constructor with the parsed GUID values.
We can scope out types that don't have a GuidAttribute for now (runtime reflection would not compute the correct GUID for them either).
Co-authored-by: Michal Strehovský <[email protected]>
Co-authored-by: Michal Strehovský <[email protected]>
Co-authored-by: Michal Strehovský <[email protected]>
Co-authored-by: Michal Strehovský <[email protected]>
var int32Type = Context.GetWellKnownType(WellKnownType.Int32); | ||
var int16Type = Context.GetWellKnownType(WellKnownType.Int16); | ||
var byteType = Context.GetWellKnownType(WellKnownType.Byte); | ||
guidType.GetParameterlessConstructor(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
guidType.GetParameterlessConstructor(); |
var int16Type = Context.GetWellKnownType(WellKnownType.Int16); | ||
var byteType = Context.GetWellKnownType(WellKnownType.Byte); | ||
guidType.GetParameterlessConstructor(); | ||
int param1 = int.Parse(parts[0], System.Globalization.NumberStyles.HexNumber); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be simpler and faster to do:
byte[] bytes = Guid.Parse(guidValue);
codeStream.EmitLdc(BinaryPrimitives.ReadInt32LittleEndian(bytes));
codeStream.EmitLdc(BinaryPrimitives.ReadInt16LittleEndian(bytes.Slice(4)));
codeStream.EmitLdc(BinaryPrimitives.ReadInt16LittleEndian(bytes.Slice(6)));
for (int i = 8; i < 16; i++)
codeStream.EmitLdc(bytes[i]);
@jkotas ready for you |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for all you hard work on this!
I do not believe my eyes that this is happens :) |
This is attempt to resurrect dotnet/corert#8143
in order to improve status of #306