8000 Upgrade to pybind11 v2.12. Fix bind_map and reconstruction.points3D by B1ueber2y · Pull Request #2502 · colmap/colmap · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Upgrade to pybind11 v2.12. Fix bind_map and reconstruction.points3D #2502

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Apr 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pycolmap/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ find_package(colmap REQUIRED)

find_package(Python REQUIRED COMPONENTS Interpreter Development.Module)

find_package(pybind11 2.11.1 REQUIRED) 8000
find_package(pybind11 2.12.0 REQUIRED)

file(GLOB_RECURSE SOURCE_FILES "${PROJECT_SOURCE_DIR}/../src/pycolmap/*.cc")
pybind11_add_module(pycolmap ${SOURCE_FILES})
Expand Down
2 changes: 1 addition & 1 deletion pycolmap/pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[build-system]
requires = ["scikit-build-core>=0.3.3", "pybind11==2.11.1"]
requires = ["scikit-build-core>=0.3.3", "pybind11==2.12.0"]
build-backend = "scikit_build_core.build"


Expand Down
164 changes: 0 additions & 164 deletions src/pycolmap/pybind11_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -128,168 +128,4 @@ class class_ext_ : public class_<type_, options...> {
}
};

// Fix long-standing bug https://github.com/pybind/pybind11/issues/4529
// TODO(sarlinpe): remove when https://github.com/pybind/pybind11/pull/4972
// appears in the next release of pybind11.
template <typename Map,
typename holder_type = std::unique_ptr<Map>,
typename... Args>
class_<Map, holder_type> bind_map_fix(handle scope,
const std::string& name,
Args&&... args) {
using KeyType = typename Map::key_type;
using MappedType = typename Map::mapped_type;
using StrippedKeyType = detail::remove_cvref_t<KeyType>;
using StrippedMappedType = detail::remove_cvref_t<MappedType>;
using KeysView = detail::keys_view<StrippedKeyType>;
using ValuesView = detail::values_view<StrippedMappedType>;
using ItemsView = detail::items_view<StrippedKeyType, StrippedMappedType>;
using Class_ = class_<Map, holder_type>;

// If either type is a non-module-local bound type then make the map binding
// non-local as well; otherwise (e.g. both types are either module-local or
// converting) the map will be module-local.
auto* tinfo = detail::get_type_info(typeid(MappedType));
bool local = !tinfo || tinfo->module_local;
if (local) {
tinfo = detail::get_type_info(typeid(KeyType));
local = !tinfo || tinfo->module_local;
}

Class_ cl(scope,
name.c_str(),
pybind11::module_local(local),
std::forward<Args>(args)...);
std::string key_type_name(detail::type_info_description(typeid(KeyType)));
std::string mapped_type_name(
detail::type_info_description(typeid(MappedType)));

// Wrap KeysView[KeyType] if it wasn't already wrapped
if (!detail::get_type_info(typeid(KeysView))) {
class_<KeysView> keys_view(scope,
("KeysView[" + key_type_name + "]").c_str(),
pybind11::module_local(local));
keys_view.def("__len__", &KeysView::len);
keys_view.def("__iter__",
&KeysView::iter,
keep_alive<0, 1>() /* Essential: keep view alive while
iterator exists */
);
keys_view.def(
"__contains__",
static_cast<bool (KeysView::*)(const KeyType&)>(&KeysView::contains));
// Fallback for when the object is not of the key type
keys_view.def(
"__contains__",
static_cast<bool (KeysView::*)(const object&)>(&KeysView::contains));
}
// Similarly for ValuesView:
if (!detail::get_type_info(typeid(ValuesView))) {
class_<ValuesView> values_view(
scope,
("ValuesView[" + mapped_type_name + "]").c_str(),
pybind11::module_local(local));
values_view.def("__len__", &ValuesView::len);
values_view.def("__iter__",
&ValuesView::iter,
keep_alive<0, 1>() /* Essential: keep view alive while
iterator exists */
);
}
// Similarly for ItemsView:
if (!detail::get_type_info(typeid(ItemsView))) {
class_<ItemsView> items_view(scope,
("ItemsView[" + key_type_name + ", ")
.append(mapped_type_name + "]")
.c_str(),
pybind11::module_local(local));
items_view.def("__len__", &ItemsView::len);
items_view.def("__iter__",
&ItemsView::iter,
keep_alive<0, 1>() /* Essential: keep view alive while
iterator exists */
);
}

cl.def(init<>());

// Register stream insertion operator (if possible)
detail::map_if_insertion_operator<Map, Class_>(cl, name);

cl.def(
"__bool__",
[](const Map& m) -> bool { return !m.empty(); },
"Check whether the map is nonempty");

cl.def(
"__iter__",
[](Map& m) { return make_key_iterator(m.begin(), m.end()); },
keep_alive<0, 1>() /* Essential: keep map alive while iterator exists */
);

cl.def(
"keys",
[](Map& m) {
return std::unique_ptr<KeysView>(
new detail::KeysViewImpl<Map, KeysView>(m));
},
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
);

cl.def(
"values",
[](Map& m) {
return std::unique_ptr<ValuesView>(
new detail::ValuesViewImpl<Map, ValuesView>(m));
},
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
);

cl.def(
"items",
[](Map& m) {
return std::unique_ptr<ItemsView>(
new detail::ItemsViewImpl<Map, ItemsView>(m));
},
keep_alive<0, 1>() /* Essential: keep map alive while view exists */
);

cl.def(
"__getitem__",
[](Map& m, const KeyType& k) -> MappedType& {
auto it = m.find(k);
if (it == m.end()) {
throw key_error();
}
return it->second;
},
return_value_policy::reference_internal // ref + keepalive
);

cl.def("__contains__", [](Map& m, const KeyType& k) -> bool {
auto it = m.find(k);
if (it == m.end()) {
return false;
}
return true;
});
// Fallback for when the object is not of the key type
cl.def("__contains__", [](Map&, const object&) -> bool { return false; });

// Assignment provided only if the type is copyable
detail::map_assignment<Map, Class_>(cl);

cl.def("__delitem__", [](Map& m, const KeyType& k) {
auto it = m.find(k);
if (it == m.end()) {
throw key_error();
}
m.erase(it);
});

// Always use a lambda in case of `using` declaration
cl.def("__len__", [](const Map& m) { return m.size(); });

return cl;
}
} // namespace PYBIND11_NAMESPACE
6 changes: 2 additions & 4 deletions src/pycolmap/scene/point3D.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,9 @@
using namespace colmap;
namespace py = pybind11;

using Point3DMap = std::unordered_map<point3D_t, Point3D>;
PYBIND11_MAKE_OPAQUE(Point3DMap);

void BindPoint3D(py::module& m) {
py::bind_map_fix<Point3DMap>(m, "MapPoint3DIdToPoint3D")
using Point3DMap = std::unordered_map<point3D_t, Point3D>;
py::bind_map<Point3DMap>(m, "MapPoint3DIdToPoint3D")
.def("__repr__", [](const Point3DMap& self) {
return "MapPoint3DIdToPoint3D(num_points3D=" +
std::to_string(self.size()) + ")";
Expand Down
8 changes: 8 additions & 0 deletions src/pycolmap/scene/reconstruction.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ using namespace colmap;
using namespace pybind11::literals;
namespace py = pybind11;

using Point3DMap = std::unordered_map<point3D_t, Point3D>;
PYBIND11_MAKE_OPAQUE(Point3DMap);

bool ExistsReconstructionText(const std::string& path) {
return (ExistsFile(JoinPaths(path, "cameras.txt")) &&
ExistsFile(JoinPaths(path, "images.txt")) &&
Expand Down Expand Up @@ -77,13 +80,18 @@ void BindReconstruction(py::module& m) {
.def_property_readonly("images",
&Reconstruction::Images,
py::return_value_policy::reference_internal)
.def("image", py::overload_cast<image_t>(&Reconstruction::Image))
.def_property_readonly("image_pairs", &Reconstruction::ImagePairs)
.def("image_pair",
py::overload_cast<image_pair_t>(&Reconstruction::ImagePair))
.def_property_readonly("cameras",
&Reconstruction::Cameras,
py::return_value_policy::reference_internal)
.def("camera", py::overload_cast<camera_t>(&Reconstruction::Camera))
.def_property_readonly("points3D",
&Reconstruction::Points3D,
py::return_value_policy::reference_internal)
.def("point3D", py::overload_cast<point3D_t>(&Reconstruction::Point3D))
.def("point3D_ids", &Reconstruction::Point3DIds)
.def("reg_image_ids", &Reconstruction::RegImageIds)
.def("exists_camera", &Reconstruction::ExistsCamera)
Expand Down
0