Skip to content

Commit

Permalink
Spelling fixes and doc tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
bschwind committed Jun 30, 2023
1 parent 0badb64 commit 3012a2b
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 8 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Rust bindings to OpenCascade. The code is currently a major work in progress.
## Major Goals
* Define 3D CAD models suitable for 3D printing or machining, in ergonomic Rust code
* Code-first approach, but allow use of a GUI where it makes sense (2D sketches)
* Support fillets, chamfers, lofts, surface filling, pipes, extrusions, lathes, etc.
* Support fillets, chamfers, lofts, surface filling, pipes, extrusions, revolutions, etc.
* Support quick compile times for faster iterations
* Ability to import/export STEP files, STL files, SVG, DXF, KiCAD files, and hopefully more!
* Easy to install the viewer app (provide pre-built binaries for major platforms)
Expand All @@ -17,11 +17,11 @@ Rust bindings to OpenCascade. The code is currently a major work in progress.

This project was born out of me designing [my own keyboard](https://github.com/bschwind/key-ripper) and wanting to make a 3D-printed or CNCed aluminum case for it. In typical over-engineering fashion, I didn't want to just use Fusion360 and call it a day. I wanted a fully parameterized, fully open-source, code-based approach so I can easily make changes, and store the model code in version control. I also want to be fairly confident I can build these models any time in the future given I have a C++/Rust toolchain available.

So I researched what kernels are out there, learned that OpenCascade is one of the few open-source B-Rep (boundary representation) kernels out there, and started writing bindings to it with cxx.rs to see if usage of the kernel is feasible. Turns out it is!
So I researched what kernels are out there, learned that OpenCascade is one of the few open-source B-Rep (boundary representation) kernels available, and started writing bindings to it with cxx.rs to see if usage of the kernel is feasible. Turns out it is!

### Why Rust?

At this point I'm most comfortable with Rust, so most tools I build will be with Rust. I also don't find any joy in creating my own language or forcing people to learn a new one. Rust is a far better language than I could ever make myself, and contains pretty much every facility I would want for defining 3D models in code. Ultimately it's a hobby project and when you run a hobby project, you get to pick whatever you want :)
At this point I'm most comfortable with Rust, so most tools I build will be with Rust. I also don't find any joy in creating my own language or forcing people to learn one I created. Rust is a far better language than I could ever make myself, and contains pretty much every facility I would want for defining 3D models in code. Ultimately it's a hobby project and when you run a hobby project, you get to pick whatever you want :)

There are other benefits:

Expand Down Expand Up @@ -54,7 +54,7 @@ There are low level examples which are more or less directly calling OpenCascade

### Higher Level

The [higher level examples](./crates/opencascade/examples) use more ergonomic Rust APIs, though the exact API is still in flux and subject ot change.
The [higher level examples](./crates/opencascade/examples) use more ergonomic Rust APIs, though the exact API is still in flux and subject to change.

## Viewer Application

Expand Down
12 changes: 8 additions & 4 deletions docs/writing_bindings.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Binding to OpenCascade Classes and Functions

OpenCascade is a huge C++ project, spanning mulitple decades. It has an impressive amount of functionality packed in, though it is somewhat hidden behind a (in my opinion) ugly/intimidating API.
OpenCascade is a huge C++ project, spanning multiple decades. It has an impressive amount of functionality packed in, though it is somewhat hidden behind a (in my opinion) ugly/intimidating API.

One goal of this project is to expose a more ergonomic and approachable API on top of the goodies within OpenCascade so more people can use it to build cool things. OpenCascade leans pretty hard into C++, and so we need to use something more than just `bindgen` in order to have Rust call it safely.

Expand Down Expand Up @@ -35,6 +35,10 @@ There are some rules to how we define these functions in our code:
* From what I can tell, generics don't work from Rust to C++ templates. If you have a C++ type called `Handle<Edge>`, you'll need to declare your own C++ type called `HandleEdge` or whatever you want, and alias it to the full type (ex:`typedef opencascade::handle<Edge> HandleEdge;`
* You can use `#[cxx_name = "SomeCPPFunctionName"]` to tell `cxx` the _real_ name of the C++ function you want to use, and `#[rust_name = "some_rust_fn_name"]` to control what the name of the function is exposed to the Rust side of things. If you don't use these attributes, the exported Rust function is exactly the same as the C++ function name.

#### Getting a `Pin<&mut T>`

If you have a `some_var: UniquePtr<T>`, you can get a `Pin<&mut T>` by calling `some_var.pin_mut()`. `some_var` must be declared as `mut` to use this.

#### `construct_unique`

Providing bindings to C++ constructors is somewhat [tricky](https://github.com/dtolnay/cxx/issues/280) and not well supported in cxx. At the same time, we can't have functions with return `T` directly, it needs to return either a reference or a smart pointer as stated previously.
Expand Down Expand Up @@ -110,7 +114,7 @@ type STEPControl_Reader;
pub fn STEPControl_Reader_ctor() -> UniquePtr<STEPControl_Reader>;
```

Mercifully, the reader constructor requires zero parameters. But the next step, reading a from a file, requires us to pass a String argument for the file name. cxx provides some facilities for converting between Rust strings and C++ strings, but now we'll have to define a function manually in `wrapper.hxx`.
Mercifully, the reader constructor requires zero parameters. But the next step, reading from a file, requires us to pass a String argument for the file name. cxx provides some facilities for converting between Rust strings and C++ strings, but now we'll have to define a function manually in `wrapper.hxx`.

```rust
pub fn read_step(
Expand Down Expand Up @@ -143,7 +147,7 @@ This means we can have functions which return `IFSelect_ReturnStatus` directly i

### Step 2 - Write the wrapper C++ code

The wrapper functions usually end up being trivial, they usually just have an easy-to-bind signature from Rust and then do whatever translation is required. In this case, we're returning an enum that is declared
The wrapper functions usually end up being trivial, they usually just have an easy-to-bind signature from Rust and then do whatever translation is required. In this case, we're returning an enum that is declared.

```c++
inline IFSelect_ReturnStatus read_step(STEPControl_Reader &reader, rust::String theFileName) {
Expand Down Expand Up @@ -216,7 +220,7 @@ How do you know which libraries to link? If you look up `STEPControl_Reader` you

![TKSTEP](./images/cascade_library.png)

The rest of the libraries were found through trial and error. The linker will complain that symbols are missing, so copy-paste those symbols into a search engine, find them on OpenCascade's documentation site, and note which library they came from.
The rest of the libraries were found through trial and error. The linker will complain that symbols are missing, so copy-paste those symbols into a search engine, find them on OpenCascade's documentation site, and note which library they came from. Alternatively, you could poke through the project's CMake and other build files to determine which libraries you need to link to.

### Step 6 - Give it a nicer Rust API

Expand Down

0 comments on commit 3012a2b

Please sign in to comment.