-
Notifications
You must be signed in to change notification settings - Fork 3.3k
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
How to use TypeScript declarations for Emscripten #10271
Comments
cc @jgravelle-google (maybe this could benefit from interface types?) |
If I understand correctly, this is about using C++ functions in a TypeScript application? And ideally having TS types for the C++ as well. Probably the most ergonomic tool would be using embind's |
@jgravelle-google Right. This is the current available way for someone who want to use C/C++ functions in a TS application right now. I am not asking Emscripten devs to do something. I posted this because I cannot find any guides on how to achieve this on the internet, and I thought posting it as an issue here is better than writing it in my blog because someone might have a better idea. As you mention, In the future we could automatically generate .d.ts using embind or the WebIDL binder. I believe #9674 and #7083 already discuss about it. |
Oh, I assumed you weren't yeah. Just thinking out loud "if I were to do this what would I do," in case that counts as having a better idea. And also thinking about how Interface Types would apply here specifically. WebIDL binder is probably closer to what TS would expect. Is there already a general-purpose .d.ts generator from webidl for web APIs? Though I imagine there's still some bridging needed to make the formats line up. |
I think microsoft/TSJS-lib-generator is the best bet. The TypeScript Team do not hand-write Web API type definitions from scratch but generate .d.ts files from various WebIDL sources (Source: microsoft/TypeScript#3027). I haven't done any experiments with this but I guess we need some work to adapt it to Emscripten. |
@jgravelle-google With protobuj.js supporting typescript, and the fact we're moving to a place where we'll want to interop across multiple languages (typescript, mono/c#, golang, rust, kotlin, c++, etc.) within the browser/webassembly, would it make more sense to focus on good protobuf support for emscripten? Then we can start using "event bus" patterns within the browser/webassembly to interop across different webassembly languages. |
I have written a tool that can generate type definitions for emscripten modules. For now i have tested it only with the ammo.js project The tool itself is based on the https://github.com/microsoft/TSJS-lib-generator. Unfortunately TSJS-lib-generator itself can not be used for emscripten as it is very specific in some parts. I borrowed some code and concepts to make it work for ammo and hopefully for other emscripten projects as well. Just needs some more testing to discover edge cases. |
Very interesting @giniedp ! If you think it's ready, a PR to add a link to that in the docs would be great. |
Hi! Im super new to typescript, and fairly novice with javascript. I was looking at the code above, and I am a bit confused. I have a very simple c file, with an add method like above, and I have compiled it using this command:
Im not sure how I go from having this simple.js file to importing it into a typescript file and running it using ts-node. I am guessing I need to write the files above, but I dont know how they connect to the wasm/js file generated with emcc, or how to use them to actually run the web assembly. My goal in this is to run some webassembly of some c code I am writing in an angular app. There are some guides, but I cant seem to figure them out if they arent outdated. |
Doesn't the rust webassembly stuff have good support for typescript? I'm wondering if rust webassembly linked w/ emscripten webassembly, especially if the rust was generated, could be another path to getting generated typescript bindings? |
There is also the whole thing of using protobufs to describe marshaled api's. Protobuf.js already has this covered for typescript. I "think" rust webassembly has good support for it too. Which brings me back to the idea of generating rust somehow, linking w/ emscripten, and then running the api via protobufjs/typescript. Some are arguing about performance of protobufs, ie the overhead of zigzag integer encoding. When laying out a protobuf schema, there are scalars which don't get zigzag encoded at runtime. So, the protobuf schema author has a choice with respect to choosing performance over the serialized encoding size. In a nutshell, I'm not sure the argument has legs. |
Hi @Michael-Pascale I am in the same dilemma as you were. I have the emcc built js and wasm files and I need to import them into a typescript react app. |
I added a basic example, please refer to~ |
I really wish this was implemented. "Being able to check that types are the same of both sides of the FFI barrier" feels like an extremely basic use-case, and yet it's doesn't seem to be covered anywhere in the wasm ecosystem. That's fine if your wasm library is intended to be imported directly from the html file and take control of the entire app (which is basically the emscripten golden path, since it's the one you see in eg in-browser game engines), but if you want to export a wasm library as JS somehow, then the lack of type safety becomes painful fast. Honestly, the fact that tickets like this have existed basically since WebAssembly came out with no progress in sight is a pretty bad omen for the wasm ecosystem. At the very least, it tells me that the ecosystem isn't interested in my use-cases (basically anything that isn't a video game or a tech demo). |
Thank you for this, it seems that people do not write documentation anymore, only bug reports. It took me a lot of swearing to understand what is actually going on here. The fact that TypeScript uses magical comments to import magical modules installed from NPM is not what I expected! The fact that it gives utterly incomprehensible error messages like "statements are not allowed in ambient contexts" when you misplace a semicolon doesn't help either. I have a library (https://github.com/ReadAlongs/SoundSwallower) compiled with There are lots of more obvious and elegant examples of WASM libraries but they seem to be written in Rust, and I am not ready to rewrite my C code in Rust, though that would surely be a good idea. Nor do I want to be forced to use C++, which instantly bloats your code the instant you touch its standard library (and, it seems, maybe even if you don't). The Here is my /// <reference types="emscripten" />
/* the comment above is magic */
declare class Config {
/* do not declare the constructor, but declare everything else here */
get(key: string): string|number;
/* ... other methods */
}
interface SoundSwallowerModule extends EmscriptenModule {
get_model_path(string): string; /* a function */
Config: { /* a class, but just its constructor */
new(dict?: Object): Config;
}
/* ... other functions and classes */
}
declare const Module: EmscriptenModuleFactory<SoundSwallowerModule>;
export default Module; And my test code: import soundswallower_factory from "soundswallower";
import {SoundSwallowerModule, Config} from "soundswallower";
(async () => {
const soundswallower: SoundSwallowerModule = await soundswallower_factory();
const config: Config = new soundswallower.Config();
console.log(config.get("samprate"));
})(); |
Am I correct in understanding that the state of the art here is the wit format and wit-bindgen? Could emscripten itself generate a wit? |
Or actually, if I'm understanding correctly, this is predicated on supporting interface types period, which emscripten doesn't do, and I don't know what the state of the spec actually is at this point |
@dhdaines great comment. And thanks for your blog series about TypeScript modules With Emscripten and CMake, which were an unvalueable help to me along my quest. |
Thanks! They might be out of date, as the Emscripten maintainers have fixed many of the issues that I ran into (and to be fair many of them are not Emscripten's fault...) |
I believe so.
In fact, I'm fidgeting with the idea of developing a Clang plugin for generating interface files from C++ headers. The choice of files would be:
Of course, only the C++ features that have a direct mapping to the concepts in each of these formats would be supported. Any thoughts? |
It looks like it hasn't been mentioned yet, but embind now supports TypeScript generation from bindings. |
the .d.ts is the interface, but where is the extend or implement ? the cpp implement function but typescript not ? |
Related: #9674 #7083
I would like to discuss the current best way to use typing features of TypeScript with Emscripten. If you are looking for a WebIDL -> TypeScript .d.ts converter for C++ application specifically, you may refer to the above two issues.
I recently found @types/emscripten from NPM and I spent a few hours to figure out how to integrate it with my Emscripten project and contributed the package a little bit too. The
.d.ts
typing file can be found here: https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/emscripten/index.d.tsSuppose I make
add.c
like this:Two ways I have figured out:
add--post-js.ts
add.d.ts
+add--post-js.js
In my case I found option 2 is better. Will be explained later.
1.
add--post-js.ts
add—post-js.ts
2.
add.d.ts
+add--post-js.js
add.d.ts
add—post-js.js
I know, both of them don't particularly look pretty but they are the cleanest ones so far.
I found that the second one is better for two reasons:
add--post-js.ts
file must be compiled to js in order to work withemcc
command. And there are problems when you want to useexport
statement because-s MODULARIZE=1
creates another export statement automatically.Please share any better tricks if you have one. Also you will notice that @types/emscripten is not complete when you look at the source code it would be great if anyone can make the package better.
Thanks :)
The text was updated successfully, but these errors were encountered: