Skip to content

Comments

Replace [DllImport] with [LibraryImport] for runtime P/Invokes#10763

Merged
jonathanpeppers merged 12 commits intomainfrom
copilot/replace-dllimport-with-libraryimport
Feb 20, 2026
Merged

Replace [DllImport] with [LibraryImport] for runtime P/Invokes#10763
jonathanpeppers merged 12 commits intomainfrom
copilot/replace-dllimport-with-libraryimport

Conversation

Copy link
Contributor

Copilot AI commented Feb 4, 2026

Summary

Convert ALL [DllImport] to [LibraryImport] for P/Invokes across the codebase.

Changes

  • RuntimeNativeMethods.cs: All 18 xa-internal-api P/Invokes
  • JNIEnvInit.cs: xamarin_app_init
  • Logger.cs: __android_log_print (liblog)
  • AndroidEnvironment.cs: exit (libc)
  • JNIEnv.cs: 3 libjnigraphics.so bitmap P/Invokes
  • Logging.cs / JavaInteropRuntime.cs (NativeAOT): 3 P/Invokes
  • AndroidRuntime.cs: Updated callers (StringBuilderstring)
  • Mono.Android.Runtime.csproj: LangVersion 10 → 12 (required for LibraryImport source generator)
  • AssemblyInfo.cs (NativeAOT): Added [assembly: DisableRuntimeMarshalling] (required for LibraryImport with ref struct parameter)

Build Fixes

  1. Updated LangVersion to 12 for LibraryImport source generator support
  2. Replaced collection expressions with array syntax (new[] { typeof(...) })
  3. Added [assembly: DisableRuntimeMarshalling] for NativeAOT project (required when passing structs by reference with LibraryImport)
  4. Added missing [UnmanagedCallConv] attributes to NativeAOT P/Invokes for consistency
Original prompt

This section details on the original issue you should resolve

<issue_title>[CoreCLR] Consider replacing [DllImport] with [LibraryImport] for p/invokes</issue_title>
<issue_description>### Android framework version

net11.0-android (Preview)

Affected platform version

.NET 11

Description

Docs: https://learn.microsoft.com/en-us/dotnet/standard/native-interop/pinvoke-source-generation

When it's not using source generation, the built-in interop system in the .NET runtime generates an IL stub—a stream of IL instructions that is JIT-ed—at runtime to facilitate the transition from managed to unmanaged. [...] Since this IL stub is generated at runtime, it isn't available for ahead-of-time (AOT) compiler or IL trimming scenarios.

We should consider replacing our [DllImport] with [LibraryImport] to reduce the amount of code that needs to be JITted at runtime and allow R2R to precompile more code into native code.

We should focus only on P/Invokes into CoreCLR host code. We do not need to make changes to Mono P/Invokes.

Steps to Reproduce

Did you find any workaround?

No response

Relevant log output

```</issue_description>

## Comments on the Issue (you are @copilot in this section)

<comments>
</comments>

💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 2 commits February 4, 2026 14:07
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Copilot AI changed the title [WIP] Consider replacing DllImport with LibraryImport for p/invokes Replace [DllImport] with [LibraryImport] for NativeAOT P/Invokes Feb 4, 2026
Copilot AI requested a review from simonrozsival February 4, 2026 14:14
Copilot AI and others added 2 commits February 4, 2026 14:48
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
…sistently

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Copilot AI changed the title Replace [DllImport] with [LibraryImport] for NativeAOT P/Invokes Replace [DllImport] with [LibraryImport] for runtime P/Invokes Feb 4, 2026
…n to 12

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
@simonrozsival
Copy link
Member

@copilot build failed:

/Users/runner/work/1/s/android/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs(44,143): error SYSLIB1051: Runtime marshalling must be disabled in this project by applying the 'System.Runtime.CompilerServices.DisableRuntimeMarshallingAttribute' to the assembly to enable marshalling this type. The generated source will not handle marshalling of parameter 'initArgs'. (https://learn.microsoft.com/dotnet/fundamentals/syslib-diagnostics/syslib1051) [/Users/runner/work/1/s/android/src/Microsoft.Android.Runtime.NativeAOT/Microsoft.Android.Runtime.NativeAOT.csproj::TargetFramework=net11.0]

…ruct parameter

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 5, 2026

@copilot build failed:

/Users/runner/work/1/s/android/src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs(44,143): error SYSLIB1051: Runtime marshalling must ...

Fixed in 34970c1. Added [assembly: DisableRuntimeMarshalling] to the NativeAOT AssemblyInfo.cs, which is required when using LibraryImport with struct parameters passed by reference (the ref JNIEnvInit.JnienvInitializeArgs initArgs parameter in XA_Host_NativeAOT_OnInit).

@simonrozsival
Copy link
Member

@copilot we need to update apk sizes. there is documentation how to do it in Documentation/project-docs/ApkSizeRegressionChecks.md, so I believe you should be able to follow it to update the baselines:

apkdiff regression test failed with exit code: 3. See test attachments.
Expected: True
But was: False

at Xamarin.Android.Build.Tests.BuildTest2.BuildReleaseArm64(Boolean forms, AndroidRuntime runtime) in /Users/builder/azdo/_work/4/s/android/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs:line 366

  1. at Xamarin.Android.Build.Tests.BuildTest2.BuildReleaseArm64(Boolean forms, AndroidRuntime runtime) in /Users/builder/azdo/_work/4/s/android/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs:line 366

Also, propose how to turn Documentation/project-docs/ApkSizeRegressionChecks.md into a SKILL.md that we could add to this repo. Feel free to commit it to this PR branch if you know how to do it.

Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 12, 2026

@copilot we need to update apk sizes. there is documentation how to do it in Documentation/project-docs/ApkSizeRegressionChecks.md, so I believe you should be able to follow it to update the baselines...

I've added a SKILL.md proposal in .github/skills/apk-size-regression.md (commit 8377833) based on the documentation. It provides structured instructions for AI assistants on how to handle APK size regression failures.

Regarding the baseline update: I cannot access the Azure Pipelines CI artifacts directly from this environment. The test results with the new .apkdesc files need to be downloaded from the failed CI build and committed. The files that need updating are in:

  • src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64*.apkdesc

Would you be able to download the artifacts from the CI and either commit them or share them so I can update the baselines?

@jonathanpeppers jonathanpeppers marked this pull request as ready for review February 19, 2026 22:39
Copilot AI review requested due to automatic review settings February 19, 2026 22:39
@jonathanpeppers
Copy link
Member

I reverted the skill -- just because I don't believe it will work:

### From CI Artifacts (Preferred)
1. Navigate to the failed CI build
2. Download the test results archive from the build artifacts
3. Extract the new `.apkdesc` files from the archive
4. Replace the corresponding files in the reference directories listed above
5. Commit the updated reference files

I don't see how it will know to go to the right AzDO instance, figure out the right artifact, etc.

We can bring this skill back, but we should test it locally -- can add it in a PR with a screenshot/example?

We could make the skill include the UpdateApkSizeReference.sh/ps1 script, for example.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR converts all [DllImport] P/Invoke declarations to [LibraryImport] for CoreCLR runtime interop, enabling source-generated marshalling code instead of runtime IL stub generation. This improves AOT compilation and reduces JIT overhead for .NET CoreCLR apps on Android.

Changes:

  • Converted 18 P/Invokes in RuntimeNativeMethods.cs plus additional P/Invokes in Logger.cs, JNIEnvInit.cs, AndroidEnvironment.cs, JNIEnv.cs, and NativeAOT runtime files to use LibraryImport
  • Changed StringBuilder parameters to string in gref/lref logging methods (safe for CoreCLR as native code treats these as const)
  • Added [assembly: DisableRuntimeMarshalling] to NativeAOT project for struct reference parameters
  • Updated APK size baselines to reflect the ~4KB increase from generated marshalling code

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/Mono.Android/Android.Runtime/RuntimeNativeMethods.cs Converted 18 xa-internal-api P/Invokes to LibraryImport with StringMarshalling.Utf8 and UnmanagedCallConv attributes
src/Mono.Android/Android.Runtime/JNIEnvInit.cs Converted xamarin_app_init P/Invoke to LibraryImport
src/Mono.Android/Android.Runtime/Logger.cs Converted __android_log_print (liblog) P/Invoke to LibraryImport
src/Mono.Android/Android.Runtime/AndroidEnvironment.cs Converted exit (libc) P/Invoke to LibraryImport
src/Mono.Android/Android.Runtime/JNIEnv.cs Converted 3 libjnigraphics.so bitmap P/Invokes to LibraryImport
src/Mono.Android/Android.Runtime/AndroidRuntime.cs Changed StringBuilder to string for gref/lref logging stack traces (safe for CoreCLR as native code doesn't modify)
src/Microsoft.Android.Runtime.NativeAOT/AssemblyInfo.cs Added DisableRuntimeMarshalling assembly attribute required for LibraryImport with ref struct parameters
src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/Logging.cs Converted __android_log_print P/Invoke to LibraryImport with fully-qualified CallConvCdecl
src/Microsoft.Android.Runtime.NativeAOT/Android.Runtime.NativeAOT/JavaInteropRuntime.cs Converted 2 xa-internal-api P/Invokes to LibraryImport (missing UnmanagedCallConv attributes)
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64XFormsDotNet.MonoVM.apkdesc Updated APK size baseline (+4KB)
src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Resources/Base/BuildReleaseArm64SimpleDotNet.MonoVM.apkdesc Updated APK size baseline (+4KB)

@jonathanpeppers
Copy link
Member

@copilot apply changes based on the comments in this thread

…eclarations

Co-authored-by: jonathanpeppers <840039+jonathanpeppers@users.noreply.github.com>
Copy link
Contributor Author

Copilot AI commented Feb 19, 2026

@copilot apply changes based on the comments in this thread

Added the missing [UnmanagedCallConv (CallConvs = new[] { typeof (CallConvCdecl) })] attributes to both LibraryImport declarations in JavaInteropRuntime.cs in commit 9f7c562.

@jonathanpeppers jonathanpeppers merged commit 8b37054 into main Feb 20, 2026
3 of 6 checks passed
@jonathanpeppers jonathanpeppers deleted the copilot/replace-dllimport-with-libraryimport branch February 20, 2026 14:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[CoreCLR] Consider replacing [DllImport] with [LibraryImport] for p/invokes

4 participants