/ src / examples / python / example.cpp
example.cpp
  1  // example.cpp
  2  // nanobind example: C++ functions callable from Python
  3  //
  4  // This demonstrates the pattern for Python/C++ interop:
  5  // - Write performance-critical code in C++
  6  // - Expose via nanobind bindings
  7  // - Call from Python with zero-copy where possible
  8  
  9  #include <cmath>
 10  #include <numeric>
 11  #include <string>
 12  #include <vector>
 13  
 14  #include <nanobind/nanobind.h>
 15  #include <nanobind/stl/string.h>
 16  #include <nanobind/stl/vector.h>
 17  
 18  namespace nb = nanobind;
 19  
 20  // =============================================================================
 21  // Pure C++ functions (the actual implementation)
 22  // =============================================================================
 23  
 24  namespace aleph {
 25  
 26  // Simple function: add two numbers
 27  int add(int a, int b) {
 28    return a + b;
 29  }
 30  
 31  // String manipulation
 32  std::string greet(const std::string& name) {
 33    return "Hello from aleph, " + name + "!";
 34  }
 35  
 36  // Vector operations (demonstrates zero-copy potential)
 37  double dot_product(const std::vector<double>& a, const std::vector<double>& b) {
 38    if (a.size() != b.size()) {
 39      throw std::runtime_error("Vector sizes must match");
 40    }
 41    return std::inner_product(a.begin(), a.end(), b.begin(), 0.0);
 42  }
 43  
 44  // Compute norm
 45  double norm(const std::vector<double>& v) {
 46    return std::sqrt(dot_product(v, v));
 47  }
 48  
 49  // A simple class
 50  class Counter {
 51  public:
 52    Counter(int initial = 0) : value_(initial) {}
 53  
 54    void increment() { ++value_; }
 55    void decrement() { --value_; }
 56    void add(int n) { value_ += n; }
 57    int get() const { return value_; }
 58    void reset() { value_ = 0; }
 59  
 60    std::string repr() const { return "Counter(" + std::to_string(value_) + ")"; }
 61  
 62  private:
 63    int value_;
 64  };
 65  
 66  } // namespace aleph
 67  
 68  // =============================================================================
 69  // nanobind module definition
 70  // =============================================================================
 71  
 72  NB_MODULE(example, m) {
 73    m.doc() = "aleph example module: C++ called from Python via nanobind";
 74  
 75    // Simple functions
 76    m.def("add", &aleph::add, "Add two integers", nb::arg("a"), nb::arg("b"));
 77  
 78    m.def("greet", &aleph::greet, "Generate a greeting", nb::arg("name"));
 79  
 80    // Vector functions
 81    m.def("dot_product", &aleph::dot_product, "Compute dot product of two vectors", nb::arg("a"),
 82          nb::arg("b"));
 83  
 84    m.def("norm", &aleph::norm, "Compute Euclidean norm of a vector", nb::arg("v"));
 85  
 86    // Class binding
 87    nb::class_<aleph::Counter>(m, "Counter")
 88        .def(nb::init<int>(), nb::arg("initial") = 0)
 89        .def("increment", &aleph::Counter::increment)
 90        .def("decrement", &aleph::Counter::decrement)
 91        .def("add", &aleph::Counter::add, nb::arg("n"))
 92        .def("get", &aleph::Counter::get)
 93        .def("reset", &aleph::Counter::reset)
 94        .def("__repr__", &aleph::Counter::repr);
 95  
 96    // Module-level test function (called by buck2 run)
 97    m.def("test", []() {
 98      // Run some basic tests
 99      bool ok = true;
100  
101      // Test add
102      if (aleph::add(2, 3) != 5) {
103        ok = false;
104      }
105  
106      // Test dot product
107      std::vector<double> a = {1.0, 2.0, 3.0};
108      std::vector<double> b = {4.0, 5.0, 6.0};
109      double expected = 32.0; // 1*4 + 2*5 + 3*6
110      if (std::abs(aleph::dot_product(a, b) - expected) > 1e-10) {
111        ok = false;
112      }
113  
114      // Test Counter
115      aleph::Counter c(10);
116      c.increment();
117      if (c.get() != 11) {
118        ok = false;
119      }
120  
121      if (ok) {
122        nb::print("example module: all tests passed");
123      } else {
124        nb::print("example module: TESTS FAILED");
125      }
126    });
127  }