Skip to content

Commit 0549c8d

Browse files
committed
Avoid linker errors when compiling for AOT.
Using Marshal.SizeOf(typeof(T)) or Enum.GetValues(typeof(T)) can cause AOT builds to fail when including the Google.Protobuf NuGet package and using the tools from a recent enough .NET SDK (9.0.300 or possibly earlier). Set <TrimmerSingleWarn>false</TrimmerSingleWarn> and <TreatWarningsAsErrors>True</TreatWarningsAsErrors> to see something like this: /_/csharp/src/Google.Protobuf/Collections/RepeatedField.cs(714): AOT analysis error IL3050: Google.Protobuf.Collections.RepeatedField`1.TryGetArrayAsSpanPinnedUnsafe(FieldCodec`1<T>,Span`1<Byte>&,GCHandle&): Using member 'System.Runtime.InteropServices.Marshal.SizeOf(Type)' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. Marshalling code for the object might not be available. Use the SizeOf<T> overload instead. [/src/xxxx/xxxx.csproj] /root/.nuget/packages/microsoft.dotnet.ilcompiler/9.0.5/build/Microsoft.NETCore.Native.targets(317,5): error MSB3073: The command ""/root/.nuget/packages/runtime.linux-x64.microsoft.dotnet.ilcompiler/9.0.5/tools/ilc" @"obj/Release/net9.0/linux-x64/native/RootApp.HubServer.ilc.rsp"" exited with code -1. [/src/xxxx/xxxx.csproj]
1 parent c7030f4 commit 0549c8d

File tree

2 files changed

+13
-4
lines changed

2 files changed

+13
-4
lines changed

csharp/src/Google.Protobuf/Collections/RepeatedField.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,13 @@ private unsafe bool TryGetArrayAsSpanPinnedUnsafe(FieldCodec<T> codec, out Span<
711711
// 1. protobuf wire bytes is LittleEndian only
712712
// 2. validate that size of csharp element T is matching the size of protobuf wire size
713713
// NOTE: cannot use bool with this span because csharp marshal it as 4 bytes
714-
if (BitConverter.IsLittleEndian && (codec.FixedSize > 0 && Marshal.SizeOf(typeof(T)) == codec.FixedSize))
714+
if (BitConverter.IsLittleEndian && (codec.FixedSize > 0 &&
715+
#if NETSTANDARD1_2_OR_GREATER || NET451_OR_GREATER || NET
716+
Marshal.SizeOf<T>()
717+
#else
718+
Marshal.SizeOf(typeof(T))
719+
#endif
720+
== codec.FixedSize))
715721
{
716722
handle = GCHandle.Alloc(array, GCHandleType.Pinned);
717723
span = new Span<byte>(handle.AddrOfPinnedObject().ToPointer(), array.Length * codec.FixedSize);

csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.cs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,12 @@ private static IReadOnlyDictionary<Edition, FeatureSetDescriptor> BuildEditionDe
4141
var featureSetDefaults = FeatureSetDefaults.Parser.ParseFrom(Convert.FromBase64String(DefaultsBase64));
4242
var ret = new Dictionary<Edition, FeatureSetDescriptor>();
4343

44-
// Note: Enum.GetValues<TEnum> isn't available until .NET 5. It's not worth making this conditional
45-
// based on that.
46-
var supportedEditions = ((Edition[]) Enum.GetValues(typeof(Edition)))
44+
var supportedEditions =
45+
#if NET5_0_OR_GREATER
46+
Enum.GetValues<Edition>()
47+
#else
48+
((Edition[])Enum.GetValues(typeof(Edition)))
49+
#endif
4750
.OrderBy(x => x)
4851
.Where(e => e >= featureSetDefaults.MinimumEdition && e <= featureSetDefaults.MaximumEdition);
4952

0 commit comments

Comments
 (0)