Skip to content

Commit

Permalink
Fix for Integer Format Check in Python SID Adapter (#1632)
Browse files Browse the repository at this point in the history
Python integer format char is ambiguous and platform dependent. PyBind11 `format_descriptor<...>::format()` always returns "q" and "Q" for 64bit integers, independent of the platform. Compatible passed-in Python buffers on the other hand might also have the equivalent format "l" or "L" set. See pybind/pybind11#1806 and pybind/pybind11#1908 for details. This fix introduces a special case for integer format comparisons, just checking size and signedness.
  • Loading branch information
fthaler authored Apr 12, 2021
1 parent 2072fd2 commit 477f700
Showing 1 changed file with 16 additions and 2 deletions.
18 changes: 16 additions & 2 deletions include/gridtools/storage/adapter/python_sid_adapter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#include <array>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <memory>
#include <stdexcept>
#include <string>
Expand Down Expand Up @@ -85,10 +86,23 @@ namespace gridtools {
if (info.itemsize != sizeof(T))
throw std::domain_error("buffer has incorrect itemsize: " + std::to_string(info.itemsize) +
"; expected " + std::to_string(sizeof(T)));

using format_desc_t = pybind11::format_descriptor<std::remove_const_t<T>>;
if (info.format != format_desc_t::format())
auto expected_format = format_desc_t::format();
assert(info.format.size() == 1 && expected_format.size() == 1);
const char *int_formats = "bBhHiIlLqQnN";
const char *int_char = std::strchr(int_formats, info.format[0]);
const char *expected_int_char = std::strchr(int_formats, expected_format[0]);
if (int_char && expected_int_char) {
// just check upper/lower case for integer formats which indicates signedness (itemsize already checked)
// direct format comparison in not enough, for details see
// https://github.com/pybind/pybind11/issues/1806 and https://github.com/pybind/pybind11/issues/1908
if (std::islower(*int_char) != std::islower(*expected_int_char))
throw std::domain_error("incompatible integer formats: " + info.format + " and " + expected_format);
} else if (info.format != expected_format) {
throw std::domain_error(
"buffer has incorrect format: " + info.format + "; expected " + format_desc_t::format());
"buffer has incorrect format: " + info.format + "; expected " + expected_format);
}
return {std::move(info)};
}

Expand Down

0 comments on commit 477f700

Please sign in to comment.