-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Description
Description
Normally, Mono WASM replaces unsupported DllImports with stubs, that throw an exception in runtime.
For example, if I declare any parameter with [MarshalAs(UnmanagedType.IUnknown)] in the DllImport:
[DllImport("ole32.dll")]
internal static extern void ReleaseStgMedium([MarshalAs(UnmanagedType.IUnknown)] ref object medium);
It will work as expected - compiler won't crash, and code is successfully executed unless this DllImport method is actually called in runtime.
But if I move [MarshalAs(UnmanagedType.IUnknown)] to the argument struct, Mono AOT compiler crashes with marshalling conversion 27 not implemented error.
In the example below, I used ReleaseStgMedium and STGMEDIUM just to reproduce the issue.
It crashes because STGMEDIUM struct is defined with unsupported marshalling type:
[MarshalAs(UnmanagedType.IUnknown)]
public object? pUnkForRelease;
Reproduction Steps
- Create browser-wasm project from a template.
- Modify Program.cs:
public static void Main(string[] args)
{
Console.WriteLine("Hello, Browser!");
DoStuff(args.FirstOrDefault());
Console.WriteLine("After DoStuff");
}
private static void DoStuff(string key)
{
if (key == "test-windows")
{
var s = new STGMEDIUM();
ReleaseStgMedium(ref s);
}
// Other branches for other platforms that we don't care in this repro.
}
[DllImport("ole32.dll")]
internal static extern void ReleaseStgMedium(ref STGMEDIUM medium);Expected behavior
Assembly and the app are compiled successfully.
Ideally, compiler outputs a warning/message about unsupported DllImport.
Faulty DllImport is replaced with a stub that throws in runtime, instead of crashing the compiler.
Actual behavior
WasmRepro failed with 2 error(s) (2.2s) → bin\Release\net9.0\browser-wasm\publish\
C:\Program Files\dotnet\packs\Microsoft.NET.Runtime.WebAssembly.Sdk\9.0.0-preview.5.24306.7\Sdk\WasmApp.Common.targets(696,5): error :
Precompiling failed for E:\Work\Projects\WasmRepro\WasmRepro\obj\Release\net9.0\browser-wasm\wasm\for-publish\aot-in\aot-instances.dll with exit code -1073740791.
marshalling conversion 27 not implemented
C:\Program Files\dotnet\packs\Microsoft.NET.Runtime.WebAssembly.Sdk\9.0.0-preview.5.24306.7\Sdk\WasmApp.Common.targets(696,5): error :
Precompiling failed for E:\Work\Projects\WasmRepro\WasmRepro\obj\Release\net9.0\browser-wasm\wasm\for-publish\aot-in\ClassLibrary.dll with exit code -1073740791.
Mono Ahead of Time compiler - compiling assembly E:\Work\Projects\WasmRepro\WasmRepro\obj\Release\net9.0\browser-wasm\wasm\for-publish\aot-in\ClassLibrary.dll
marshalling conversion 27 not implemented
WasmRepro failed (2.5s) → bin\Release\net9.0\browser-wasm\publish\
Regression?
As far as I can tell, the same behavior was in .NET 8 and .NET 7.
Known Workarounds
Use Cecil or trimming descriptor files to exclude these specific dll imports from compilation.
Configuration
.NET 9 preview5
Windows 11
browser wasm
any browser
Other information
Other platform RIDs, like linux, macOS as well as mobile mono do support such DllImports without issues as far as I can tell.
It causes inconsistency
In ideal world, where we have access to the fauly code, we would replace these DllImports with safer alternatives or added OperatingSystem.IsWindows checks. But we can't do that, as in real world this code is hidden somewhere inside closed source third party dependency, making it completely unsable.