-
Notifications
You must be signed in to change notification settings - Fork 102
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
Manually generate signatures for some PInvokes to handle SetLastError. #1354
Conversation
CsWinRT/src/cswinrt/strings/WinRT.cs Lines 32 to 36 in cc36846
Shouldn't these signatures translate to |
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.
As a general rule: if a library is multi-targeting, unless very extreme cases where not possible, do not make compromises on the latest target by using downlevel APIs everywhere. Instead, add necessary polyfills only on the downlevel target, and use the best approach on the latest one.
My two cents: like with previous changes in this file, I'm not really sure this is worth the effort at all right now, as this is not code we should keep. We need to bump the TFM for CsWinRT to .NET 8 (I guess once it goes GA), and then only handle NS2.0 and .NET 8, where on the .NET 8 we'll be able to just use |
.NET 6 introduced the following APIs in order to aid scenarios involving namespace System.Runtime.InteropServices;
public static partial class Marshal
{
public static int GetLastSystemError();
public static int GetLastPInvokeError();
public static void SetLastSystemError(int error);
public static void SetLastPInvokeError(int error);
} The point of these APIs was not simply convenience either. Prior to .NET 6, it was not possible to directly call To solve this, when your P/Invoke is annotated with In short, you should never manually P/Invoke The changes proposed in this PR do not account for this behavior, and are therefore unsafe on targets older than .NET 6. The correct solution is to conditionally use #if NET7_0_OR_GREATER
[LibraryImport("kernel32.dll", SetLastError = true)]
internal static unsafe partial IntPtr LoadLibraryExW(ushort* fileName, IntPtr fileHandle, uint flags);
#else
[DllImport("kernel32.dll", SetLastError = true)]
internal static unsafe extern IntPtr LoadLibraryExW(ushort* fileName, IntPtr fileHandle, uint flags);
#endif Though as you can see, this only takes effect on .NET 7 and higher (because |
@manodasanW plans on moving away from the .NET 6 TFM? |
I'll update the PR with multitargeting given some of the concerns raised about doing this correct downlevel. I don't see .NET 6 getting dropped soon. |
Changed to only use new signatures on .NET 6 and newer. |
We will need to continue supporting .NET 6 as it is an LTS. But I am exploring what it means to have both .NET 6 and .NET 8 versions of the Windows SDK projection. With that said, given we are a targeting pack, it is looking like it is going to require .NET SDK changes first before that can be done so I won't take a dependency on that for now. |
* Fix issues from dictionary caching (#1353) * Add tests to exercise different ABI types for generic of dictionary * Revert lookup cache to fix rests where ABI Signature can be different. * Bring over API compat validation updates * Undo comment * Undo one more comment * Simplify factory generated code. (#1355) * Include CsWInRT.exe in the inputs so MSBuild reruns the target if CsWinRT.exe got updated. (#1356) * Manually generate signatures for some PInvokes to handle SetLastError. (#1354) * Manually generate signatures to handle SetLastError. * Use new signatures on .NET 6 and newer. * Use sbyte* --------- Co-authored-by: Manodasan Wignarajah <mawign@microsoft.com> --------- Co-authored-by: Johan Laanstra <jlaans@microsoft.com>
Mimicks the generated code from LibraryImport but with handrolled Get/SetLastError as it's not available everywhere.