Skip to content
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Use custom marshaller for auto-encoding strings.
  • Loading branch information
teo-tsirpanis committed Sep 21, 2025
commit b2d6edf1d4b2dba9c6939d720569bf2899d1112a
27 changes: 18 additions & 9 deletions src/MSBuildLocator/NativeMethods.cs
Original file line number Diff line number Diff line change
Expand Up @@ -46,23 +46,23 @@ internal static int hostfxr_resolve_sdk2(string exe_dir, string working_dir, hos
}
}

[LibraryImport(HostFxrName, StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(HostFxrName, StringMarshallingCustomType = typeof(AutoStringMarshaller))]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
private static unsafe partial int hostfxr_resolve_sdk2(
string exe_dir,
string working_dir,
hostfxr_resolve_sdk2_flags_t flags,
delegate* unmanaged[Cdecl]<hostfxr_resolve_sdk2_result_key_t, ushort*, void> result);
delegate* unmanaged[Cdecl]<hostfxr_resolve_sdk2_result_key_t, void*, void> result);

[ThreadStatic]
private static string t_resolve_sdk2_resolved_sdk_dir, t_resolve_sdk2_global_json_path;

[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
private static unsafe void hostfxr_resolve_sdk2_callback(hostfxr_resolve_sdk2_result_key_t key, ushort* value)
private static unsafe void hostfxr_resolve_sdk2_callback(hostfxr_resolve_sdk2_result_key_t key, void* value)
{
Debug.Assert(t_resolve_sdk2_resolved_sdk_dir is null);
Debug.Assert(t_resolve_sdk2_global_json_path is null);
string str = Utf16StringMarshaller.ConvertToManaged(value);
string str = AutoStringMarshaller.ConvertToManaged(value);
switch (key)
{
case hostfxr_resolve_sdk2_result_key_t.resolved_sdk_dir:
Expand Down Expand Up @@ -92,24 +92,33 @@ internal static int hostfxr_get_available_sdks(string exe_dir, out string[] sdks
}
}

//[DllImport(HostFxrName, CharSet = CharSet.Auto, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)]
[LibraryImport(HostFxrName, StringMarshalling = StringMarshalling.Utf16)]
[LibraryImport(HostFxrName, StringMarshallingCustomType = typeof(AutoStringMarshaller))]
[UnmanagedCallConv(CallConvs = [typeof(CallConvCdecl)])]
private static unsafe partial int hostfxr_get_available_sdks(string exe_dir, delegate* unmanaged[Cdecl]<int, ushort**, void> result);
private static unsafe partial int hostfxr_get_available_sdks(string exe_dir, delegate* unmanaged[Cdecl]<int, void**, void> result);

[ThreadStatic]
private static string[] t_get_available_sdks_result;

[UnmanagedCallersOnly(CallConvs = [typeof(CallConvCdecl)])]
private static unsafe void hostfxr_get_available_sdks_callback(int count, ushort** sdks)
private static unsafe void hostfxr_get_available_sdks_callback(int count, void** sdks)
{
string[] result = new string[count];
for (int i = 0; i < count; i++)
{
result[i] = Utf16StringMarshaller.ConvertToManaged(sdks[i]);
result[i] = AutoStringMarshaller.ConvertToManaged(sdks[i]);
}
t_get_available_sdks_result = result;
}

[CustomMarshaller(typeof(string), MarshalMode.Default, typeof(AutoStringMarshaller))]
internal static unsafe class AutoStringMarshaller
{
public static void* ConvertToUnmanaged(string s) => (void*)Marshal.StringToCoTaskMemAuto(s);

public static void Free(void* ptr) => Marshal.FreeCoTaskMem((nint)ptr);

public static string ConvertToManaged(void* ptr) => Marshal.PtrToStringAuto((nint)ptr);
}
}
}
#endif