dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.2k stars 1.57k forks source link

C++ interop #42210

Closed lukapercic closed 4 years ago

lukapercic commented 4 years ago

Hi, I was wondering if there is any plan to make wrapping our own C++ libraries into flutter easy. dart:ffi is a great start, but it doesn't support C++ api, just C.

To make it usable, we have to wrap all C++ calls into C, and then call them via dart:ffi, which takes a lot of time and its hard to maintain; extend.

Also, FFI doesn't provide any automation in making glue code between Flutter and underlying FFI code. You have to write it manually. Are there any plans to automate that part?

I was looking at flutter roadmap, but there don't seem to be any mention of improvements for C++ bindings.

Cheers!

devoncarew commented 4 years ago

cc @mraleph

mraleph commented 4 years ago

There are no plans to support direct C++ interop, because of the complexity. We also are not directly planning to implement bindings generators. However we are open to community to step up and provide bindings generator - which is something that relatively easily can be done on top of FFI. And we have already seen interest in that from the community.

AFAIK there somebody working on one as part of Google Summer of Code - @dcharkes can provide more details here.

dcharkes commented 4 years ago

Yes, we a GSoC project, I'll keep you posted when we do a first release.

dcharkes commented 4 years ago

Yes, we a GSoC project, I'll keep you posted when we do a first release.

We have released https://pub.dev/packages/ffigen.

bog-dan-ro commented 4 years ago

@dcharkes why did you closed this issue? ffigen can handle only plain C not C++ ...

Also I'd like to ask dart devs if they researched what people want? I bet you that most of the people that had to port any application to Android which needed performance, they had to compile their C++ code and use the JNI hell to connect it to the Java world, and I also bet you that they hated that part a lot.

IMHO if you want dart to succeed, you have to listen to what people want not what you think they want.

Someone who went trough all the JNI hell will not do it again. If you want dart to be used everywhere, I really think you should give us proper C++ interop, I'm not dreaming for something as easy as Qt <-> QML integration, but at least something like boost.python/pybind11.

lukapercic commented 4 years ago

We also had a bad experience with gluing our C++ core code to Android via JNI and sure wouldn't want to go that way again.

At the moment we're using Qt for our (security) app frontend GUI but were looking for an easy way to port it to Flutter and leave c++ core for the backend. For now, It looks like we better stick to Qt as porting to Flutter via C wrapper looks way too much overhead for our small team and it could also potentially introduce unintended security holes.

mraleph commented 4 years ago

We understand that you might want even simpler interoperability with C++, however as a team we have limited bandwidth so we have to keep ourselves laser focused on things that only we can provide leaving the rest to the community. In this particular case a low-level low-overhead way to interact with C APIs is something that only we can provide. However once this functionality is provided in the form of dart:ffi all higher level functionality, e.g. interacting with C++ APIs, can be built on top of it by the community.

I invite you to either contribute to package ffigen or start a project like boost::dartbind soliciting contributions from other engineers and teams with similar needs. If necessary would be happy to help you by making changes to dart:ffi (if some crucial functionality is missing), but we currently have no plans to implement any sort of direct C++-binding tooling or library ourselves as we simply don't have bandwidth for that.

bog-dan-ro commented 4 years ago

@mraleph I understand that google has no bandwidth for it, but I still don't understand why this task is closed :). The title and the description are about C++ not C, so please keep the task open.

Back to C++ suport, it might be possible to change dart VM to do it the Qt way? E.g. directly embed dart vm into a C++ application, and have a way to directly export a C++ types and classes to dart VM? Of course we'll have to explicitly add some meta information about the types and classes. This also means we'll need some parts of the dart VM C++ API public.

FWIW dart is not the only new language that has this problem, swift folks realized that without a proper C++ integration swift will never beat ObjC++ in popularity (see https://github.com/apple/swift/blob/main/docs/CppInteroperabilityManifesto.md). It's not ideal but comparing to ffigen it's light years away ;-).

dcharkes commented 4 years ago

I understand that google has no bandwidth for it, but I still don't understand why this task is closed :).

My bad, I closed the issue because of the second question that was asked by the OP was assigned to me. And that was solved with package:ffigen.

mraleph commented 4 years ago

I still don't understand why this task is closed :).

I think it is fair to keep it closed to reflect that we have no plans to work on it.

Back to C++ suport, it might be possible to change dart VM to do it the Qt way? E.g. directly embed dart vm into a C++ application, and have a way to directly export a C++ types and classes to dart VM?

I am not sure what "Qt way" means, but yes you can embed Dart VM into your Qt application, if you so choose. This is how Flutter embeds Dart VM. Dart VM has public C API for embedders (https://github.com/dart-lang/sdk/blob/master/runtime/include/dart_api.h), which you can use to reflectively access Dart and expose native methods to it. I'd however discourage you from using that for various reasons, as FFI is a preferred way of binding Dart and native worlds.

lukapercic commented 4 years ago

Found this very promising C++ ⮜⮞ Dart bindings generator
https://github.com/heremaps/gluecodium

Hopefully, it gets some more love from the community and the industry to turn it into full-fledged automatic binder :)

bog-dan-ro commented 3 years ago

Back to C++ suport, it might be possible to change dart VM to do it the Qt way? E.g. directly embed dart vm into a C++ application, and have a way to directly export a C++ types and classes to dart VM?

I am not sure what "Qt way" means, but yes you can embed Dart VM into your Qt application, if you so choose. This is how Flutter embeds Dart VM. Dart VM has public C API for embedders (https://github.com/dart-lang/sdk/blob/master/runtime/include/dart_api.h), which you can use to reflectively access Dart and expose native methods to it. I'd however discourage you from using that for various reasons, as FFI is a preferred way of binding Dart and native worlds.

@mraleph The Qt way means a way to register Dart classes/packages directly from C/C++ (check https://doc.qt.io/qt-5/qtqml-cppintegration-topic.html to see how easy it is) . I checked dart_api.h (and the other .h files from the same folder) but I could not found anything to do it. Is it something that I missed? This will enable us to create a library similar to pybind11. The idea is to register Dart classes/packages directly from C/C++ without any additional .dart files.

gluecodium is a great project, but it needs a bit more boilerplate :).

mraleph commented 3 years ago

The Qt way means a way to register Dart classes/packages directly from C/C++.

Unfortunately this is not something that we are going to support, because this simply will not work with AOT compilation. AOT compiler only sees Dart source so it will not be able to know about your dynamically registered classes.

If you really want you can kinda make this work in JIT mode by synthesising Dart source in memory, but again this will be swimming against the current.

bog-dan-ro commented 3 years ago

The Qt way means a way to register Dart classes/packages directly from C/C++.

Unfortunately this is not something that we are going to support, because this simply will not work with AOT compilation. AOT compiler only sees Dart source so it will not be able to know about your dynamically registered classes.

Aha, now it makes more sense.

If you really want you can kinda make this work in JIT mode by synthesising Dart source in memory, but again this will be swimming against the current.

I'm a good swimmer, I can swim a few km against the current ;-), but it seems it's in vain.

geiseri commented 3 years ago

In qml they dlopen a base "plugin" that will more or less forward a k,v structure of function pointers to their interpreter. This can be done with the current FFI if you ignore all type safety (in the end everything is a void* anyway). In Qt they cheat because they have a static structure in each object that contains the layout as well as respective function pointers to the symbols. As much as I am not a fan of moc maybe if there was a "layout" structure that could be defined and populated this could be consumed the same way as structs are in ffi with the C symbols. In the end, they are all string lookups. That being said, the structs packing approach has always been a minefield and they always end up going back to a generic synthetic object like COM typelibs or IDL or something else horrible. So in the end maybe the gluecodium approach will be the last one standing.