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