Skip to content

Commit

Permalink
working on cxx julia interface docs
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdjscott committed Apr 17, 2024
1 parent 9b479d9 commit a634d12
Showing 1 changed file with 65 additions and 3 deletions.
68 changes: 65 additions & 3 deletions docs/src/tutorials/modifying-the-cxx-side-of-the-interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ Note that there are two sides to the interface:
The Julia interface on the C++ side is created using [CxxWrap.jl](https://github.com/JuliaInterop/CxxWrap.jl), which is documented in the *README.md* file in their git repo.

!!! note
It is assumed that you have successfully followed the tutorial to [set up your development environment](setting-up-your-development-environment.md).
It is assumed that you have successfully followed the tutorial to [set up your development environment](setting-up-your-development-environment.md). It is also assumed that you will refer to the [CxxWrap.jl documentation](https://github.com/JuliaInterop/CxxWrap.jl).

## Switch to your dace directory

Expand Down Expand Up @@ -40,7 +40,7 @@ JLCXX_MODULE define_julia_module(jlcxx::module& mod) {
}
```
All the methods and types defined within the `define_julia_module` function will belong to the generated Julia module when we load it in the *DACE.jl* package.
All the methods and types defined within the `define_julia_module` function using `mod` will belong to the generated Julia module when we load it in the *DACE.jl* package.
Refer also to the [CxxWrap.jl module entry point documentation](https://github.com/JuliaInterop/CxxWrap.jl?tab=readme-ov-file#module-entry-point).
Expand Down Expand Up @@ -83,7 +83,7 @@ You can return values back to Julia and CxxWrap.jl can automatically infer the t
mod.method("getEps", []() { return DA::getEps(); });
```

is a lambda function (`[]`) that takes no arguments (`()`) and returns the epsilon value `return DA::getEps();` and automatically convert the C++ return type to a Julia type.
is a lambda function (`[]`) that takes no arguments (`()`) and returns the epsilon value `return DA::getEps();` and automatically converts the C++ return type to a Julia type.

It is also possible to specify the return type, which we have done in some cases to avoid compiler warnings, e.g. we specify the return type of `getMaxOrder` to be of type `int64_t` here:

Expand All @@ -93,4 +93,66 @@ mod.method("getMaxOrder", []()->int64_t { return DA::getMaxOrder(); });
## Adding the DA type
Refer to the CxxWrap.jl documentation about [exposing C++ classes](https://github.com/JuliaInterop/CxxWrap.jl?tab=readme-ov-file#exposing-classes).
C++ classes are exposed to Julia using `mod.add_type<>()`, for example we expose the `DA` class with:
```cxx
// add the DA object
mod.add_type<DA>("DA", jlcxx::julia_type("Real", "Base"))
```

Here the template parameter, `<DA>`, is the C++ class to expose, the first argument `"DA"` is the name of corresponding type to create in Julia and the optional second argument can be used to specify which type the new type should inherit from. In this case the Julia `DA` type will inherit from the Julia `Real` type (`jlcxx::julia_type("Real", "Base")`).

Different constructors for the new type can be added, here we define three constructors:

```cxx
mod.add_type<DA>("DA", jlcxx::julia_type("Real", "Base"))
.constructor<>()
.constructor<const double>()
.constructor<const int, const double>()
```

- `.constructor<>()`: the default constructor that takes no arguments
- `.constructor<const double`(): the `DA` constructor that takes a single double as an argument
- `.constructor<const int, const double>()`: the `DA` constructor that takes and integer and double

CxxWrap will automatically call the correct C++ constructor that matches the arguments in the template parameters.

## Adding methods to the DA type

Methods can be chained onto the `mod.add_type` or defined separately. An example of chaining a method is:

```cxx
mod.add_type<DA>("DA", jlcxx::julia_type("Real", "Base"))
.constructor<>()
.constructor<const double>()
.constructor<const int, const double>()
.method("toString", &DA::toString);
```

After the three constructors we also add `DA::toString` as a method in the Julia module named `toString`. CxxWrap will automatically make the first argument of the method a `DA` type because we have chained it onto the `mod.add_type<DA>()`.

We can also directly add `DA` methods using:

```cxx
mod.method("gamma", [](const DA& da) { return da.GammaFunction(); });
```
which creates a `"gamma"` Julia method that is called with a `DA` as the first argument and returns the result of calling the C++ `DA` member function `da.GammaFunction()`.
## Adding methods to another module
So far, whenever we use `mod.method` or `mod.add_type` it adds the methods and types to our new Julia module. We can add methods to another module, such as the Julia Base module, using
```cxx
mod.set_override_module(jl_base_module);
// all methods here are added to the base module
mod.method("+", [](const DA& da1, const DA& da2) { return da1 + da2; });
mod.method("+", [](const DA& da, const double c) { return da + c; });
mod.method("+", [](const double c, const DA& da) { return c + da; });
// until we call this, then subsequent calls to mod.method will add methods to our module again
mod.unset_override_module();
```

0 comments on commit a634d12

Please sign in to comment.