pybind / pybind11_abseil

Pybind11 bindings for the Abseil C++ Common Libraries
Other
23 stars 13 forks source link

Support for absl::InlinedVector<T, N>? #3

Open jiawen opened 2 years ago

jiawen commented 2 years ago

I have a function that returns absl::InlinedVector<float, 4>, as well as a struct that contains one as a member.

I'm happy to implement this but would like to entertain suggestions for API design, especially for generic types T.

jiawen commented 2 years ago

Perhaps we can just use stl_bind directly?

rwgk commented 2 years ago

It's the first time I hear about absl::InlinedVector tbh, but aha! In some other life I called something similar af::small (af = array family), it came complete with Boost.Python "tuple mappings". It was/is really simple and it's been working just fine for nearly a couple decades. Maybe that could be our starting point for absl::InlinedVector & pybind11?

High-level, here is what accumulated over all those years (to show that it's not a lot): https://github.com/cctbx/cctbx_project/blob/e1d0279224910b350cc131a872bbaf938bbf59f5/scitbx/array_family/boost_python/flex_ext.cpp#L100

And here is the implementation: https://github.com/cctbx/cctbx_project/blob/e1d0279224910b350cc131a872bbaf938bbf59f5/scitbx/boost_python/container_conversions.h#L277

rwgk commented 2 years ago

Perhaps we can just use stl_bind directly?

Possibly. I don't know too much about the details of it.

jiawen commented 2 years ago

Confirmed that this works fine. Snippet:

#include "pybind11/stl_bind.h"
#include "pybind11_abseil/absl_casters.h"

namespace py = ::pybind11;

PYBIND11_MAKE_OPAQUE(absl::InlinedVector<int, 4>);

namespace my_namespace {
namespace {

void applyBindings(pybind11::module_& m) {
  py::bind_vector<absl::InlinedVector<int, 4>>(m, "InlinedVector_int_4");
}

}  // namespace
}  // namespace my_namespace
a = InlinedVector_int_4()
a.append(6)
a.append(-5)
print(a)

b = InlinedVector_int_4([2, 5, -6)
print(b)

I even tried this with absl::InlinedVector<MyCPlusPlusEnumClass, 3> and it worked fine.

rwgk commented 2 years ago

Just a comment: py::bind_vector creates a whole new Python type, in other words, a significant amount of machine code. These things add up. Copying between InlinedVector and a native Python tuple is much more lightweight (I believe, I don't have actual measurements).

jiawen commented 2 years ago

Makes sense. This suffices for my use purpose (statically setting some values in a struct at startup).

Mapping a Python tuple, list, or iterable to C++ would mean iterating over it and calling obj.cast<CType>(item), which will work fine I suppose. In my use case, it would mean binding a lambda to the struct property. Cool.