Skip to content
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

Possibly deprecate embind for nbind #4770

Closed
k2snowman69 opened this issue Dec 3, 2016 · 5 comments
Closed

Possibly deprecate embind for nbind #4770

k2snowman69 opened this issue Dec 3, 2016 · 5 comments
Labels

Comments

@k2snowman69
Copy link

Essentially it seems that innovation for embind has slowed and a competitor has come up, nbind. It seems that nbind is able to do everything embind can do but is a short syntax and also generates out a typescript definition file which is extremely important for modern day development.

I'm opening this issue to help facilitate the answering of the following questions:

  1. Are there any currently planed features for embind in the works
  2. Is nbind really a superset of embind and if not, what features are missing to close that gap
  3. Once that gap is closed, does it make sense to deprecate embind

Let me know if the question needs more clarifying.

@k2snowman69 k2snowman69 changed the title Add documentation for nbind to website Possibly deprecate embind for nbind Dec 3, 2016
@k2snowman69
Copy link
Author

Just to note, this issue was requested from the google group:
https://groups.google.com/forum/#!topic/emscripten-discuss/HuExyt3g-u8

@juj
Copy link
Collaborator

juj commented Dec 4, 2016

There are multiple different conversations bundled into one in this bug report, which I think would be best separated to individual aspects.

  • First, nbind lives in a separate repository, whereas embind is currently shipped as part of the Emscripten repository. Before we decide whether to deprecate embind, there should be a consideration of if shipping nbind as part of Emscripten would make sense and what that would look like.
  • There is no pressing need to choose an official binding mechanism for C++ to JS, so deprecating embind in favor of nbind is not necessary, but they can both easily exist side by side. Deprecating means an eventual disruption to people who currently use embind, and telling them to migrate to nbind would not be good, unless we have a migration guide and a good understanding that all embind use cases will be covered by nbind, or otherwise people can get annoyed.
  • It is true that development on embind has practically stopped, and there has not been an active maintainer on it for a while. Still, it is currently useful for a number of things, and has a strong unit test suite for what it currently supports, and a documentation page on how to use it. Even though it does have a number of reported shortcomings/missing features, it does work for the cases that are verified in the suite, which is a valuable feature to have.

So, if we wanted to deprecate embind in favor of nbind, it is not something we should even decide on now, but would be a multiple step project, where 1. nbind was first integrated to Emscripten repository and the two would live side by side, 2. the current embind use cases are converted over to nbind (in the form of a migration guide), 3. once people have switched over to nbind, we could consider deprecating embind, but that should be a decision to naturally fall out of obsolescence (nobody is using embind anymore, because everyone is using nbind instead).

There is no current pressing need to get to step 3, but we could just stop at step 1 as well, especially because it is imaginable that step 2 can be a very large undertaking for anyone to start working on.

Even if integrating nbind to Emscripten was not interesting, another path of action might be to document its existence, installation and usage in Emscripten docs, which would point to its separate repository to obtain it. This probably depends on what @jjrv feels would make most sense for the nbind project?

@juj juj added the embind label Dec 4, 2016
@jjrv
Copy link
Contributor

jjrv commented Dec 4, 2016

First of all, point 2 from @k2snowman69. Here's the main embind features that I know nbind is missing:

  • Function overloading by number of arguments. Only constructors can be overloaded on nbind. Function overloading based on number and types of arguments is planned, but multiple inheritance support makes it more complicated.
  • External constructors. With nbind you bind the factory function, which can return a new instance (preferably using std::shared_ptr), so a C++ factory function simply becomes a JavaScript factory function.
  • Non-member-functions on the JavaScript prototype. Currently with nbind you need a bit of glue code on the JavaScript side to add a function to the prototype and pass this as the first argument.
  • Deriving from C++ classes in JavaScript. You can inherit the class, but JavaScript side cannot override virtual C++ methods so that other C++ code would automatically call the JavaScript implementation.
  • Automatic downcasting. This is planned soon: Add a policy for automatic return value downcasting charto/nbind#36
  • Enums. I tend to use TypeScript const enum on JavaScript side, since the enum names are replaced by their values in compiled output. For example inside nbind there's an identical C++ enum and TypeScript enum. The contents can be copy-pasted between them.
  • Constants. This would be easy to implement, but so far hasn't been needed.
  • emval. nbind's nbind::External is a black box that can hold JavaScript values but not access their contents from C++. Implementing such access in a nice way still takes some planning.
  • Closure compiler support. I don't think it works with nbind currently. Since nbind is fully typed and written in TypeScript, I'm hoping that some day a good solution comes up for using Closure compiler on TypeScript code, or another equally good type-aware minifier for it appears.

@juj's points:

nbind really shouldn't be integrated in Emscripten's repo (unless as a Git submodule) because the Node.js target is just as important. New Node.js versions sometimes require a new release, and for Node.js use only nbind is needed, not the rest of Emscripten.

The current nbind test suite really accelerates its development. All C++ testcase source files are linked together and the JavaScript-based testbench only requires launching Node.js once. That means it's reasonable to run in Travis CI and Appveyor on several versions of all supported platforms at every commit. For nbind tests, Emscripten is a precompiled binary black box maintained by the Urho3D project. I think this makes the tests more practical to run than embind's, but the overall Emscripten couldn't use this approach of course.

I don't think deprecating embind is necessary. The feature gap should be closed so that new projects could always choose nbind if they wish. Eventually a bunch of templates and macros could surely be developed to shim all embind functionality when using nbind, but I don't think it's worth the effort.

Currently emcc has a single --bind option that replaces several other options. Meanwhile nbind needs this nice list:

  • -std=c++11
  • --pre-js <path>
  • --post-js <path)>
  • --js-library <path>
  • -s EXPORTED_FUNCTIONS=["_nbind_init","_nbind_value"]
  • -s DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=["nbind_value","$Browser"]

The integration in Emscripten's code that I'd like to see some day, is a --nbind or similar option to replace the above list. But what if in the future, different versions of nbind need different options? I guess it would have to be tied to a specific major nbind version and for other versions, the full set of options is still needed.

Perhaps embind, nbind and other similar libraries should be able to define their required flags somewhere... Sounds more like the job for a build tool. Currently nbind has Gyp tooling to avoid these problems, and possibly adding appropriate Cmake configuration would be enough for Emscripten users who don't use the Node.js ecosystem.

I was asked to do a PR to add a link to nbind and a benchmark to the Emscripten docs. I haven't had time to do the benchmark, which always requires some thought to do properly and impartially. Any help would be appreciated.

@k2snowman69
Copy link
Author

Thanks for that list of features. Seems like a relatively large gap for now but it is always good to have the list. It sounds like embind's focus is low-level connection of c++ and javascript and nbind's focus is a high-level connection which much more structure. Since they are serving two purposes it makes no sense currently to choose one over the other.

I agree @jjrv that nbind really shouldn't be brought into emscripten but should be more thought as a sub-module. This does get into a question of version pinning which was touched on a bit and overall we've solved that with npm so it's not a problem that needs to be solved again.

Given the two cases it sound like the focus should be getting a link to nbind in the documentation. This would have honestly helped me a ton and I'm having to go back and recode a bunch of stuff to move it over. That said, I know nothing about benchmarking as I focus mainly on UI development but if I can help I'd love to!

@jjrv
Copy link
Contributor

jjrv commented Dec 4, 2016

The actual feature gap is:

  • Function overloading: about half a week of work to overload by argument count, but something more complicated taking 1-2 weeks of effort is planned. High priority but will be delayed.
  • Automatic downcasting: about half a week of effort. High priority.
  • emval: 1-2 weeks. Medium priority, NAPI support comes first.
  • Deriving from (and overriding) C++ classes in JavaScript: about a week of effort. Low priority.
  • Closure compiler support: probably isn't happening.

Once the first 3 items are resolved, nbind is "ready" and version 1.0.0 should be out. The other differences not on this shorter list are minor things that can be quite quickly implemented if there's a need, but they don't seem that important, and would clutter the API.

Once automatic downcasting is done, the official way to handle non-member class methods is to subclass on the C++ side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants