MONO /__w/1/s/src/mono/mono/mini/aot-runtime-wasm.c:187 при маршаллинге float в .NET9
В процессе портирования одной библиотеки на WASM обнаружил, что маршаллинг функций, которые принимают float, работает крайне нестабильно и регулярно приводит к вылету в недрах Mono.
float FloatTest (float test) { return test; } // Работает
float FloatTest (char *a, float test) { return test + a[0]; } // Вылетает
int FloatTest (char *a, float test) { return (int)test + a[0]; } // Работает
int FloatTest (float test1, float test2) { return (int)(test1 + test2); } // Вылетает
void glClearColor(float, float, float, float); // Вылетает
dotnet.native.z7t3i4ajhl.js:1294 Invalid UTF-8 leading byte 0x000000fe encountered when deserializing a UTF-8 string in wasm memory to a JS string!
warnOnce @ dotnet.native.z7t3i4ajhl.js:1294
UTF8ArrayToString @ dotnet.native.z7t3i4ajhl.js:1179
(anonymous) @ strings.ts:76
xe @ strings.ts:68
Fc @ logging.ts:110
$wasm_trace_logger @ dotnet.native.hu7iv36mbw.wasm:0x2b63e0
$eglib_log_adapter @ dotnet.native.hu7iv36mbw.wasm:0x4af3e
$monoeg_g_logv_nofree @ dotnet.native.hu7iv36mbw.wasm:0x4810f
$monoeg_g_log @ dotnet.native.hu7iv36mbw.wasm:0x48224
$monoeg_g_log_disabled @ dotnet.native.hu7iv36mbw.wasm:0x48272
$mono_wasm_get_interp_to_native_trampoline @ dotnet.native.hu7iv36mbw.wasm:0x14c780
$ves_pinvoke_method @ dotnet.native.hu7iv36mbw.wasm:0x1a34e
$mono_interp_exec_method @ dotnet.native.hu7iv36mbw.wasm:0xb4e9
$interp_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0x1b66e
$mono_jit_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0x13a58d
$do_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0xfa55a
$mono_runtime_invoke_checked @ dotnet.native.hu7iv36mbw.wasm:0xfa4f4
$mono_runtime_try_invoke_byrefs @ dotnet.native.hu7iv36mbw.wasm:0x100ca6
$ves_icall_InternalInvoke @ dotnet.native.hu7iv36mbw.wasm:0xc3b14
$ves_icall_InternalInvoke_raw @ dotnet.native.hu7iv36mbw.wasm:0xcc6be
$do_icall @ dotnet.native.hu7iv36mbw.wasm:0x1dded
$do_icall_wrapper @ dotnet.native.hu7iv36mbw.wasm:0x1a163
$mono_interp_exec_method @ dotnet.native.hu7iv36mbw.wasm:0xb3b7
$interp_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0x1b66e
$mono_jit_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0x13a58d
$do_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0xfa55a
$mono_runtime_try_invoke @ dotnet.native.hu7iv36mbw.wasm:0xfafda
$mono_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0xfdbc1
$mono_wasm_invoke_jsexport @ dotnet.native.hu7iv36mbw.wasm:0x2b66f8
(anonymous) @ dotnet.native.z7t3i4ajhl.js:811
ccall @ dotnet.native.z7t3i4ajhl.js:6744
(anonymous) @ dotnet.native.z7t3i4ajhl.js:6762
hn @ managed-exports.ts:280
(anonymous) @ managed-exports.ts:65
Pc @ run.ts:71
await in Pc (async)
(anonymous) @ main.js:32
logging.ts:129 [MONO] /__w/1/s/src/mono/mono/mini/aot-runtime-wasm.c:187 <disabled>
Error
at Fc (http://localhost:5251/_framework/dotnet.runtime.d1pzlaz2ez.js:3:168832)
at dotnet.native.wasm.wasm_trace_logger (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[13816]:0x2b63e0)
at dotnet.native.wasm.eglib_log_adapter (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[949]:0x4af3e)
at dotnet.native.wasm.monoeg_g_logv_nofree (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[845]:0x4810f)
at dotnet.native.wasm.monoeg_g_log (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[847]:0x48224)
at dotnet.native.wasm.monoeg_g_log_disabled (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[848]:0x48272)
at dotnet.native.wasm.mono_wasm_get_interp_to_native_trampoline (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[5004]:0x14c780)
at dotnet.native.wasm.ves_pinvoke_method (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[126]:0x1a34e)
at dotnet.native.wasm.mono_interp_exec_method (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[115]:0xb4e9)
at dotnet.native.wasm.interp_runtime_invoke (http://localhost:5251/_framework/dotnet.native.hu7iv36mbw.wasm:wasm-function[158]:0x1b66e)
Fc @ logging.ts:129
$wasm_trace_logger @ dotnet.native.hu7iv36mbw.wasm:0x2b63e0
$eglib_log_adapter @ dotnet.native.hu7iv36mbw.wasm:0x4af3e
$monoeg_g_logv_nofree @ dotnet.native.hu7iv36mbw.wasm:0x4810f
$monoeg_g_log @ dotnet.native.hu7iv36mbw.wasm:0x48224
$monoeg_g_log_disabled @ dotnet.native.hu7iv36mbw.wasm:0x48272
$mono_wasm_get_interp_to_native_trampoline @ dotnet.native.hu7iv36mbw.wasm:0x14c780
$ves_pinvoke_method @ dotnet.native.hu7iv36mbw.wasm:0x1a34e
$mono_interp_exec_method @ dotnet.native.hu7iv36mbw.wasm:0xb4e9
$interp_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0x1b66e
$mono_jit_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0x13a58d
$do_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0xfa55a
$mono_runtime_invoke_checked @ dotnet.native.hu7iv36mbw.wasm:0xfa4f4
$mono_runtime_try_invoke_byrefs @ dotnet.native.hu7iv36mbw.wasm:0x100ca6
$ves_icall_InternalInvoke @ dotnet.native.hu7iv36mbw.wasm:0xc3b14
$ves_icall_InternalInvoke_raw @ dotnet.native.hu7iv36mbw.wasm:0xcc6be
$do_icall @ dotnet.native.hu7iv36mbw.wasm:0x1dded
$do_icall_wrapper @ dotnet.native.hu7iv36mbw.wasm:0x1a163
$mono_interp_exec_method @ dotnet.native.hu7iv36mbw.wasm:0xb3b7
$interp_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0x1b66e
$mono_jit_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0x13a58d
$do_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0xfa55a
$mono_runtime_try_invoke @ dotnet.native.hu7iv36mbw.wasm:0xfafda
$mono_runtime_invoke @ dotnet.native.hu7iv36mbw.wasm:0xfdbc1
$mono_wasm_invoke_jsexport @ dotnet.native.hu7iv36mbw.wasm:0x2b66f8
(anonymous) @ dotnet.native.z7t3i4ajhl.js:811
ccall @ dotnet.native.z7t3i4ajhl.js:6744
(anonymous) @ dotnet.native.z7t3i4ajhl.js:6762
hn @ managed-exports.ts:280
(anonymous) @ managed-exports.ts:65
Pc @ run.ts:71
await in Pc (async)
(anonymous) @ main.js:32
Минимальный пример
(на основе стандартного шаблона WebAssembly Browser App для .NET9)
// main.js
import { dotnet } from './_framework/dotnet.js'
const { setModuleImports, getAssemblyExports, getConfig, runMain } = await dotnet
.withApplicationArguments("start")
.create();
runMain();
// Program.cs
using System;
using System.Runtime.InteropServices;
internal class Program {
[DllImport("Marshal")]
public static extern int test(float test1, float test2, float test3);
private static void Main(string[] args) {
Console.WriteLine(test(123, 456, 789));
}
}
// Marshal.c
int test(float test1, float test2, float test3) {
return (int)(test1 + test2 + test3);
}
<Project Sdk="Microsoft.NET.Sdk.WebAssembly">
<PropertyGroup>
<TargetFramework>net9.0-browser</TargetFramework>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<WasmBuildNative>true</WasmBuildNative>
</PropertyGroup>
<ItemGroup>
<NativeFileReference Include="Marshal.c" />
</ItemGroup>
</Project>
Ожидается:
1368 в консоли.
На практике:
Ошибка выше по тексту.
Проблему не решили:
- Замена
[DllImport]на[LibraryImport](без эффекта). - Откат до .NET8 (без эффекта, другим помогало при схожих проблемах).
[MarshalAs(UnmanagedType.U4)]на авось, в попытке пропустить маршаллинг дляfloat(без эффекта).
При этом если собрать пример с AOT, то он начинает магическим образом работать.
Более того, после выключения AOT и даже очистки проекта, все скомпилированные ранее с AOT импорты продолжают работать, но только не новые, добавленные после последней AOT компиляции. Но это не касается отладочных сборок, они всё равно не работают (AOT с отладкой несовместим).
Вопрос: Это баг в Mono или я чего-то не понимаю? Если это не баг, то не хочется создавать бессмысленный issue. И второе: какие еще возможны решения, ибо жить вообще без отладки не хочется.