-
Notifications
You must be signed in to change notification settings - Fork 5k
Add BStrStringMarshaller
to source generator
#69213
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
Merged
AaronRobinsonMSFT
merged 12 commits into
dotnet:main
from
AaronRobinsonMSFT:runtime_69021
May 20, 2022
Merged
Changes from all commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
6206312
Add BStrStringMarshaller to source generator
AaronRobinsonMSFT f4cad5c
Update src/libraries/System.Runtime.InteropServices/tests/LibraryImpo…
AaronRobinsonMSFT 5c6e955
Change to checked addition
AaronRobinsonMSFT be406c8
Apply suggestions from code review
AaronRobinsonMSFT d52db68
Update src/libraries/System.Runtime.InteropServices/tests/LibraryImpo…
AaronRobinsonMSFT 74a2744
Update src/libraries/System.Private.CoreLib/src/System/Runtime/Intero…
AaronRobinsonMSFT 7044848
Change native type to ushort.
AaronRobinsonMSFT 4c22b52
Update System.Runtime.InteropServices.cs
AaronRobinsonMSFT e0ca27d
Update src/libraries/System.Private.CoreLib/src/System/Runtime/Intero…
AaronRobinsonMSFT 57055ae
Convert to use void* for BStr and Utf16 marshallers' native types.
AaronRobinsonMSFT 2239ffa
Merge branch 'main' into runtime_69021
AaronRobinsonMSFT 2379671
Review feedback
AaronRobinsonMSFT File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
125 changes: 125 additions & 0 deletions
125
...em.Private.CoreLib/src/System/Runtime/InteropServices/Marshalling/BStrStringMarshaller.cs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Diagnostics; | ||
using System.Runtime.CompilerServices; | ||
using System.Text; | ||
|
||
namespace System.Runtime.InteropServices.Marshalling | ||
{ | ||
/// <summary> | ||
/// Marshaller for BSTR strings | ||
/// </summary> | ||
[CLSCompliant(false)] | ||
[CustomTypeMarshaller(typeof(string), BufferSize = 0x100, | ||
Features = CustomTypeMarshallerFeatures.UnmanagedResources | CustomTypeMarshallerFeatures.TwoStageMarshalling | CustomTypeMarshallerFeatures.CallerAllocatedBuffer)] | ||
public unsafe ref struct BStrStringMarshaller | ||
{ | ||
private void* _ptrToFirstChar; | ||
private bool _allocated; | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="BStrStringMarshaller"/>. | ||
/// </summary> | ||
/// <param name="str">The string to marshal.</param> | ||
public BStrStringMarshaller(string? str) | ||
: this(str, default) | ||
{ } | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="BStrStringMarshaller"/>. | ||
/// </summary> | ||
/// <param name="str">The string to marshal.</param> | ||
/// <param name="buffer">Buffer that may be used for marshalling.</param> | ||
/// <remarks> | ||
/// The <paramref name="buffer"/> must not be movable - that is, it should not be | ||
/// on the managed heap or it should be pinned. | ||
/// <seealso cref="CustomTypeMarshallerFeatures.CallerAllocatedBuffer"/> | ||
/// </remarks> | ||
public BStrStringMarshaller(string? str, Span<ushort> buffer) | ||
{ | ||
_allocated = false; | ||
|
||
if (str is null) | ||
{ | ||
_ptrToFirstChar = null; | ||
return; | ||
} | ||
|
||
ushort* ptrToFirstChar; | ||
int lengthInBytes = checked(sizeof(char) * str.Length); | ||
|
||
// A caller provided buffer must be at least (lengthInBytes + 6) bytes | ||
// in order to be constructed manually. The 6 extra bytes are 4 for byte length and 2 for wide null. | ||
int manualBstrNeeds = checked(lengthInBytes + 6); | ||
if (manualBstrNeeds > buffer.Length) | ||
{ | ||
// Use precise byte count when the provided stack-allocated buffer is not sufficient | ||
ptrToFirstChar = (ushort*)Marshal.AllocBSTRByteLen((uint)lengthInBytes); | ||
_allocated = true; | ||
} | ||
else | ||
{ | ||
// Set length and update buffer target | ||
byte* pBuffer = (byte*)Unsafe.AsPointer(ref MemoryMarshal.GetReference(buffer)); | ||
*((uint*)pBuffer) = (uint)lengthInBytes; | ||
ptrToFirstChar = (ushort*)(pBuffer + sizeof(uint)); | ||
} | ||
|
||
// Confirm the size is properly set for the allocated BSTR. | ||
Debug.Assert(lengthInBytes == Marshal.SysStringByteLen((IntPtr)ptrToFirstChar)); | ||
|
||
// Copy characters from the managed string | ||
str.CopyTo(new Span<char>(ptrToFirstChar, str.Length)); | ||
ptrToFirstChar[str.Length] = '\0'; // null-terminate | ||
_ptrToFirstChar = ptrToFirstChar; | ||
} | ||
|
||
/// <summary> | ||
/// Returns the native value representing the string. | ||
/// </summary> | ||
/// <remarks> | ||
/// <seealso cref="CustomTypeMarshallerFeatures.TwoStageMarshalling"/> | ||
/// </remarks> | ||
public void* ToNativeValue() => _ptrToFirstChar; | ||
|
||
/// <summary> | ||
/// Sets the native value representing the string. | ||
/// </summary> | ||
/// <param name="value">The native value.</param> | ||
/// <remarks> | ||
/// <seealso cref="CustomTypeMarshallerFeatures.TwoStageMarshalling"/> | ||
/// </remarks> | ||
public void FromNativeValue(void* value) | ||
{ | ||
_ptrToFirstChar = value; | ||
_allocated = true; | ||
} | ||
|
||
/// <summary> | ||
/// Returns the managed string. | ||
/// </summary> | ||
/// <remarks> | ||
/// <seealso cref="CustomTypeMarshallerDirection.Out"/> | ||
/// </remarks> | ||
public string? ToManaged() | ||
{ | ||
if (_ptrToFirstChar is null) | ||
return null; | ||
|
||
return Marshal.PtrToStringBSTR((IntPtr)_ptrToFirstChar); | ||
} | ||
|
||
/// <summary> | ||
/// Frees native resources. | ||
/// </summary> | ||
/// <remarks> | ||
/// <seealso cref="CustomTypeMarshallerFeatures.UnmanagedResources"/> | ||
/// </remarks> | ||
public void FreeNative() | ||
{ | ||
if (_allocated) | ||
Marshal.FreeBSTR((IntPtr)_ptrToFirstChar); | ||
} | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.