Skip to content

Commit

Permalink
30: add nanobind struct example, other refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
lgarrison committed Feb 9, 2024
1 parent d39893f commit cd5de9f
Show file tree
Hide file tree
Showing 10 changed files with 74 additions and 21 deletions.
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,10 @@ _site/
.jekyll-cache/

.DS_Store
~$*
~$*

__pycache__/
.vscode/
*.o
*.so
build/
20 changes: 10 additions & 10 deletions 30_CCQ/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,15 @@ nanobind-example/
├── CMakeLists.txt
├── pyproject.toml
└── src
└── examplepkg
└── example_pkg
├── compute.py
├── examplemod.cpp
├── array_example_module.cpp
└── __init__.py
```

---

## nanobind `examplemod.cpp`
## nanobind `array_example_module.cpp`
```c++
template <typename Scalar>
void double_arr(
Expand All @@ -95,7 +95,7 @@ void double_arr(
}
}

NB_MODULE(examplemod, m) {
NB_MODULE(array_example_module, m) {
m.def("double_arr", &double_arr<float>);
m.def("double_arr", &double_arr<double>);
}
Expand All @@ -105,17 +105,17 @@ NB_MODULE(examplemod, m) {
## nanobind `compute.py`
```python
from . import examplemod
from . import array_example_module
inarr = np.arange(20)
outarr = np.empty_like(inarr)
examplemod.double_arr(outarr, inarr)
array_example_module.double_arr(outarr, inarr)
```

- Easy! nanobind will check that the array types have the expected shape, dtype, strides, etc.
- A more sophisticated example would have nanobind returning a NumPy array
- Now we'll look at how `examplemod.cpp` gets built
- Now we'll look at how `array_example_module.cpp` gets built

---

Expand All @@ -127,9 +127,9 @@ project(${SKBUILD_PROJECT_NAME} LANGUAGES CXX)
find_package(Python 3.8 COMPONENTS Interpreter Development.Module REQUIRED)
find_package(nanobind CONFIG REQUIRED)
nanobind_add_module(examplemod src/examplepkg/examplemod.cpp)
nanobind_add_module(array_example_module src/example_pkg/array_example_module.cpp)
install(TARGETS examplemod LIBRARY DESTINATION examplepkg)
install(TARGETS array_example_module LIBRARY DESTINATION example_pkg)
```

---
Expand All @@ -141,7 +141,7 @@ requires = ["scikit-build-core >= 0.5", "nanobind"]
build-backend = "scikit_build_core.build"

[project]
name = "examplepkg"
name = "example_pkg"
version = "0.0.1"
requires-python = ">=3.8"

Expand Down
6 changes: 4 additions & 2 deletions 30_CCQ/nanobind-example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ project(${SKBUILD_PROJECT_NAME} LANGUAGES CXX)
find_package(Python 3.8 COMPONENTS Interpreter Development.Module REQUIRED)
find_package(nanobind CONFIG REQUIRED)

nanobind_add_module(examplemod src/examplepkg/examplemod.cpp)
nanobind_add_module(array_example_module src/example_pkg/array_example_module.cpp)
nanobind_add_module(struct_example_module src/example_pkg/struct_example_module.cpp)

install(TARGETS examplemod LIBRARY DESTINATION examplepkg)
install(TARGETS array_example_module LIBRARY DESTINATION example_pkg)
install(TARGETS struct_example_module LIBRARY DESTINATION example_pkg)
2 changes: 1 addition & 1 deletion 30_CCQ/nanobind-example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ $ pip install -e . --no-build-isolation

## Test
```
$ python -m examplepkg.compute
$ python -m example_pkg.compute
```
2 changes: 1 addition & 1 deletion 30_CCQ/nanobind-example/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ requires = ["scikit-build-core >= 0.5", "nanobind"]
build-backend = "scikit_build_core.build"

[project]
name = "examplepkg"
name = "example_pkg"
version = "0.0.1"
requires-python = ">=3.8"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ void double_arr(nb::ndarray<Scalar, nb::ndim<1>, nb::device::cpu> outarr,
}
}


NB_MODULE(examplemod, m) {
NB_MODULE(array_example_module, m) {
m.def("double_arr", &double_arr<float>);
m.def("double_arr", &double_arr<double>);
m.def("double_arr", &double_arr<int64_t>);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
from timeit import default_timer

import numpy as np

from . import examplemod
from . import array_example_module

def main():
inarr = np.arange(20)
outarr = np.empty_like(inarr)

examplemod.double_arr(outarr, inarr)
array_example_module.double_arr(outarr, inarr)

print(inarr)
print(outarr)
Expand Down
35 changes: 35 additions & 0 deletions 30_CCQ/nanobind-example/src/example_pkg/struct_example_module.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#include <iostream>
#include <sstream>

#include <nanobind/nanobind.h>
#include <nanobind/ndarray.h>
#include <nanobind/stl/string.h>

namespace nb = nanobind;

struct S {
int i;
S(int i):i{i}{}
int m() const { return i+2;}
};

// A function using S
int f(S const & s){ return s.i;}

// make S printable in C++
std::ostream & operator<<(std::ostream &out, S const & s) {
return out << "S struct with i=" << s.i << '\n';
}

NB_MODULE(struct_example_module, m) {
nb::class_<S>(m, "S")
.def_rw("i", &S::i)
.def(nb::init<int>())
.def("m", &S::m)
.def("__repr__", [](const S& s) {
std::stringstream stream;
stream << s;
return stream.str();
});
m.def("f", &f);
}
13 changes: 13 additions & 0 deletions 30_CCQ/nanobind-example/src/example_pkg/test_struct.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
from . import struct_example_module

def main():
s = struct_example_module.S(3)
print()
print(f'{s = }')
print(f'{s.i = }')
print(f'{s.m() = }')
print(f'{struct_example_module.f(s) = }')
print()

if __name__ == '__main__':
main()

0 comments on commit cd5de9f

Please sign in to comment.