Skip to content

Commit

Permalink
Improve README
Browse files Browse the repository at this point in the history
  • Loading branch information
iamsergio committed Apr 9, 2024
1 parent 11172b1 commit 9ce85b4
Showing 1 changed file with 95 additions and 2 deletions.
97 changes: 95 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ still works as supposed to.

## Example

`example/animal.h`

```cpp
#include <iostream>

Expand All @@ -32,8 +34,15 @@ public:
};
```

<br>

`example/app/bin/main.dart`


```dart
class MyDartAlligator extends MyBindings.Animal
import 'package:AnimalBindings/Bindings.dart' as AnimalBindings;
class MyDartAlligator extends AnimalBindings.Animal
{
@override
void openMouth() {
Expand All @@ -56,7 +65,84 @@ main() {
}
```

## Problems
## Trying the example

The example living in `example/` already has the bindings pre-generated. You can play with it simply by:

```
cd example/
cmake -G Ninja .
ninja # produces libAnimal.so
cd app/
dart pub get
cd ..
# Help Dart find libAnimal.so:
export LD_LIBRARY_PATH=.:$LD_LIBRARY_PATH
dart run app/bin/main.dart
```

On macOS, just edit and hardcode the library path in `generated/AnimalBindings/dart/lib/LibraryLoader.dart` , since `DYLD_LIBRARY_PATH` isn't recommended nowadays.l

## Structure of the example
- `animal.h and animal.cpp` The C++ source code we generated bindings for.
- `animal_export.h` Export macros, generated by CMake, since we need to export symbols.
- `bindings_global.h` Contains the list of headers we generate bindings for.
- `dartagnan.json` Config read by dartagnan when generating the bindings
- `typesystem.xml` Tells dartagnan which classes and enums to generate bindings for
- `app/` The dart application which will load and use the bindings
- `generated/AnimalBindings/dart/` Auto-generated Dart package containing the bindings
- `generated/AnimalBindings/dart/ffi/` Auto-generated C++ code which is needed as an intermediary, to implement virtual dispatch.

For convenience, our `libAnimal.so`'s CMakeLists.txt builds both `animal.cpp` and the autogenerated `Animal_c.cpp`. You could also have them separated
`libAnimal.so` and `libAnimalBindings.so`, which would be better in case you're targeting a 3rdparty.

## Building Dartagnan

```
git submodule init && git submodule update
cmake --preset=dev
cd build-dev && ninja
```

## Generating your own bindings

Generating your own bindings consists basically of writing your own `typesystem.xml` file specifing what you want to generate bindings for.

Then make an invocation such as:

```
../build-dev/3rdparty/shiboken/sources/shiboken6/generator/shiboken6 \
--license-file=license_template \
--output-directory=generated \
--generator-set=dart --skip-deprecated --clang-option=-DDARTAGNAN_BINDINGS_RUN bindings_global.h typesystem.xml
clang-format -i ./generated/AnimalBindings/dart/ffi/Animal_c.cpp ./generated/AnimalBindings/dart/ffi/Animal_c.h
```

Dartagnan is based on shiboken, which is use to generated Python bindings for Qt.


## Features

- Single inheritance
- virtual methods
- static methods
- Some templates
- const char * <-> dart String is interchangeable
- Blacklisting methods via typesystem.xml (Shiboken feature)
- C++ destructors are called! calling `myCFunction(MyCType(10, 20))` creates a temporary `MyCType()` as expected and
destroys it at the end of expression. This is done with Dart Finalizers.



## Problems and why this is just a POC

- Templates are a PITA. The C++ needs to contain the specializations. You can't specialize from Dart if it wasn't beforehand
done in C++.

- Dart doesn't support more than one unnamed constructor. The generated bindings look like `MyClass.ctor1()`, `MyClass.ctor2()` etc.

- Actually, same for methods. Dart doesn't support overloading. Generated code is prefixed with numbers.

- Passing small and trivial-destructible structs to C++ is allocating memory. They should be passed via registers, or at the very least stack.

Expand All @@ -67,3 +153,10 @@ main() {
- Dartagnan is based on shiboken's Api-extractor, which is a LLVM-based C++ parser. Api extractor brings in Qt as a dependency.

- Rebasing over new shiboken, newer LLVM and newer Qt often causes regressions.

## Future

While Dartagnan works and is even being used in production for KDDockWidgets we don't have any plans to move it from POC to something serious.<br>
The shiboken legacy is quite a burden and its usage is very involved.<br>
If someone wants to write a new backend from scratch I hope Dartagnan is a useful inspiration.

0 comments on commit 9ce85b4

Please sign in to comment.