Description
LibraryImport on browser-wasm fails to resolve symbols from Emscripten side modules even when the module exists in the app bundle and dlopen would succeed. This scenario requires Emscripten dynamic linking (-s MAIN_MODULE=1 / -s SIDE_MODULE=1), which the .NET SDK does not enable by default, but the runtime should still resolve symbols correctly when it is used. Today the runtime only checks the generated pinvoke table and does not attempt dlopen for non-table names, so side modules cannot be resolved.
Reproduction Steps
- Build a browser-wasm app with Emscripten main module support:
- Link flags:
-s MAIN_MODULE=1
- Build a side module with one exported function:
emcc -O0 -s SIDE_MODULE=1 -s EXPORT_ALL=1 -o libmylib.wasm side-module.cside-module.c:
int side_add(int a, int b) { return a + b; }
- Ensure the side module is included in the app bundle (e.g.,
WasmNativeAsset with TargetPath = libmylib.wasm so it exists in the virtual FS). - Use LibraryImport in managed code (note: no extension in the name to exercise suffix probing):
[LibraryImport("libmylib", EntryPoint = "side_add")]
internal static partial int SideAdd(int a, int b);
- Run the app.
Expected behavior
LibraryImport resolves side_add from libmylib.wasm and returns correct results. Names without an explicit extension should be probed with the platform suffix (WASM: .wasm), so libmylib and libmylib.wasm are equivalent.
Actual behavior
LibraryImport fails with DllNotFoundException or EntryPointNotFoundException, despite the side module being present and dlopen being able to load it. The runtime never attempts dlopen for non-table names.
Known Workarounds
Link native code into the main module (no side module) so the symbol is present in the generated pinvoke table.
Configuration
- .NET version:
main (net11.0). - Runtime: Mono
browser-wasm. - Build flags:
WasmBuildNative=true, -s MAIN_MODULE=1 (main module), -s SIDE_MODULE=1 -s EXPORT_ALL=1 (side module).
Other information
Runtime currently prioritizes pinvoke table lookups and does not fall back to dlopen for non-table names. For dynamic linking, it should attempt dlopen(name) after the pinvoke table check and rely on the platform suffix probing (WASM: .wasm).
Description
LibraryImport on browser-wasm fails to resolve symbols from Emscripten side modules even when the module exists in the app bundle and dlopen would succeed. This scenario requires Emscripten dynamic linking (
-s MAIN_MODULE=1/-s SIDE_MODULE=1), which the .NET SDK does not enable by default, but the runtime should still resolve symbols correctly when it is used. Today the runtime only checks the generated pinvoke table and does not attempt dlopen for non-table names, so side modules cannot be resolved.Reproduction Steps
-s MAIN_MODULE=1emcc -O0 -s SIDE_MODULE=1 -s EXPORT_ALL=1 -o libmylib.wasm side-module.cside-module.c:WasmNativeAssetwithTargetPath=libmylib.wasmso it exists in the virtual FS).Expected behavior
LibraryImport resolves
side_addfromlibmylib.wasmand returns correct results. Names without an explicit extension should be probed with the platform suffix (WASM:.wasm), solibmylibandlibmylib.wasmare equivalent.Actual behavior
LibraryImport fails with
DllNotFoundExceptionorEntryPointNotFoundException, despite the side module being present and dlopen being able to load it. The runtime never attempts dlopen for non-table names.Known Workarounds
Link native code into the main module (no side module) so the symbol is present in the generated pinvoke table.
Configuration
main(net11.0).browser-wasm.WasmBuildNative=true,-s MAIN_MODULE=1(main module),-s SIDE_MODULE=1 -s EXPORT_ALL=1(side module).Other information
Runtime currently prioritizes pinvoke table lookups and does not fall back to dlopen for non-table names. For dynamic linking, it should attempt dlopen(name) after the pinvoke table check and rely on the platform suffix probing (WASM:
.wasm).