-
Notifications
You must be signed in to change notification settings - Fork 10.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is there a way I can compile small piece of C# code to wasm #46344
Comments
@anirugu There are ways of doing this, but neither of them involve Blazor. Blazor is a UI framework, but you're just looking for a way to run arbitrary .NET code on WebAssembly. The two approaches I can suggest are:
Option 1 is probably more practical for your scenario, since you will be running inside a browser. |
@mkArtakMSFT do we need a new area label for issues like this one? |
It should have gone to the runtime repo really. But in any case it's in the |
My scenario is similar to the original question, but what I'm trying to get is a single Wasm that is also not tied to either browser or WASI - akin to the wasm32-unknown-unknown target available in Clang and Rust. That is, C# compiled to Wasm shouldn't be dependant upon any host functions except those explicitly provided via custom DllImport. I understand this would limit its functionality in the same way as wasm32-unknown-unknown target does (e.g. no access to console, filesystem, timers, etc), but it would allow it to be used with custom runtimes. Is there any way to achieve that with either of Wasm targets currently available in .NET? Everything I find, even in experimental repos, seems to assume either Web or WASI hosts. |
Sorry for the slow response on this. The technique I've used in the past to eliminate all the WASI imports from the
I think that covers all the WASI imports but if any remain you can add similar stubs for those too, then the resulting |
@SteveSandersonMS Right, thanks, that covers removing imports, but how about adding imports/exports to custom runtime? Since asking that question I switched to NativeAOT-LLVM for now, which allows to just declare |
Looks like those 2 are currently TODO items in dotnet/runtime#65895:
So I guess no way to do that with Wasi.Sdk yet. |
@RReverser It is possible to define imports/exports with this SDK but currently you have to do that in C and use the Mono hosting APIs to interop with C# code. It’s inconvenient.
Interesting. Have you been able to run the result in non-browser/Node environments, or does your scenario allow for depending on JS? Last time I checked that was using Emscripten and hence involved a JS requirement. If it now supports non-JS host environments that would be extremely interesting and I’d love to know how you got that to work! |
I'd love to see an example of both imports & exports even if it's not very convenient at the moment, just to have something to compare with. Since I couldn't find a way to do that myself (and didn't get a response at the time), I started trying other solutions and .NET NativeAOT LLVM seemed most promising as imports/exports worked out of the box and, well, I know Emscripten quite well so figured might try to patch over the missing parts.
It doesn't quite support execution w/o JS (STANDALONE_WASM is somewhat limited in what it can do) but I'm currently working on an idea that might allow it. If all goes well, I'll blog about it! Exceptions support is the most tricky bit as neither of major WASI runtimes (Wasmtime & Wasmer) support Wasm exceptions yet and neither does .NET AOT LLVM, so that currently has to go via JS - that's the part I'm trying to eliminate. I'm guessing that one is not a problem for Wasi.Sdk as it bundles the .NET bytecode + interpreter so exceptions "just work"? |
See examples in the dotnet-wasi-sdk repo, e.g.
That would be the holy grail for NativeAOT-LLVM so if you do manage to make it work please let me know! It could unlock a lot of very interesting scenarios. |
That's actually not too bad. And then these two lines https://github.com/dotnet/dotnet-wasi-sdk/blob/2dbb00c779180873d3ed985e59e431f56404d8da/src/Wasi.AspNetCore.Server.Atmo/build/Wasi.AspNetCore.Server.Atmo.targets#L4-L5 are enough to include those in the build?
To be fair, it's more of a hack rather than a long-term solution, I'd still love for NativeAOT-LLVM to properly support raw WASI like was started in dotnet/runtimelab#1850, but yeah, I will! |
@SteveSandersonMS Is the list of available |
I guess it's just this? https://github.com/dotnet/runtime/blob/d11ed579a34b9650faba9275054e5990587c17f7/src/mono/wasi/mono-include/driver.h But if so, it seems pretty limited in terms of objects it can manipulate. |
Hmm no that doesn't seem to help... |
No, there's a lot more. Once you have the
Yes that is the case. Not sure why it wouldn't be working in your project. |
Sorry, something changed (I'm not sure what, I did a bunch of experiments in the last few minutes) and it builds now. It complained about unknown attribute Anyway, it builds now and I can see imports added correctly, but, no matter what I do, a native export from the C file doesn't seem to be exposed. I tried:
Those examples you linked seem to only use custom imports, any tips on how to export functions as well? |
Ah this one was because I tried putting it into So only the problem with exports remains. (and, well, digging through headers to find the necessary mono C functions) |
So I figured since
and it worked 😂 This feels extremely hacky, but I guess it at least unblocks me for now... Please let me know if there's a better way to pass extra Clang args. |
Now I'm getting some failed assertion...
|
Ohh okay that one is just because I had |
@RReverser Just guessing but calling invoking
You can mark a C function as exported or imported without needing any clang args at all: __attribute__((export_name("my_function")))
void my_function() {
...
}
I got something that does work in my situation, but no promises about yours! https://gist.github.com/SteveSandersonMS/f1a54f033d7fb78fd9c409d406398fa2 I was able to run a NativeAOT-LLVM build under wasmtime with this. |
Huh, odd that
Heh yeah that's another idea I considered, but I'm currently working on a solution that wouldn't require runtime imports at all, that is, it would work with wasmer/wasmtime out of the box :) We just don't really want to expose those imports to arbitrary users, as they're somewhat unstable plus the list of imports required by .NET might change over time. |
It's pretty cool that you got it to work though! |
How do you specify include paths for those (without hardcoding the full path)? If I try to include like |
...which is weird because I can see |
Ah looks like I was missing something, perhaps because I had |
Okay, it all comes together nicely and much quicker than with NativeAOT. The only problem I'm running into is that it seems Is such propagation expected to work or is it currently a known limitation? |
This is a general MSBuild thing, not something specific to dotnet-wasi-sdk. It's inconvenient, but to solve it you can:
There's an example of this in https://github.com/dotnet/dotnet-wasi-sdk/tree/main/src/Wasi.AspNetCore.Server.Atmo/build |
Hmm thanks but TBH if path needs to be hardcoded anyway, at that point it feels easier to leave user setting the
I guess I was hoping that if I add |
Forgot to respond to this btw - doesn't look like this is exported even in In |
It's the same for me, but I got error:
I must first call the c# Main function (_start function) before I call my custom exported function:
|
@zxyao145 Yes, that's expected. The runtime does have to be started before it's valid to call .NET methods. |
Got it, thank you very much for your reply |
Is there an existing issue for this?
Describe the bug
I have developed a Chrome extension using jQuery and then converted it to vanilla JavaScript. I am now seeking a way to improve its performance by using Blazor. Is it possible to write a basic C# code, compile it to WebAssembly (.wasm), and import and execute it in a JavaScript file?
Expected Behavior
I am looking for result similar to this post https://nodejs.dev/en/learn/nodejs-with-webassembly/
Steps To Reproduce
I discovered a project on Github (https://github.com/mingyaulee/Blazor.BrowserExtension) that has caught my interest. However, I am looking for a way to compile a single file into a single WebAssembly (.wasm) file, similar to the approach used in Angular and React projects. Is there a method I am unaware of that can achieve the same result? I prefer to avoid deploying multiple DLLs for a simple task. Is there a way in .NET that can serve this purpose?
Exceptions (if any)
NA
.NET Version
7.0.200-preview.22628.1
Anything else?
No response
The text was updated successfully, but these errors were encountered: