Skip to content

Commit

Permalink
Patching in snapshot of PR pybind#4319
Browse files Browse the repository at this point in the history
  • Loading branch information
Ralf W. Grosse-Kunstleve committed Nov 9, 2022
1 parent 3163ae2 commit 5aa6093
Show file tree
Hide file tree
Showing 7 changed files with 107 additions and 2 deletions.
9 changes: 9 additions & 0 deletions docs/classes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,15 @@ interactive Python session demonstrating this example is shown below:
Static member functions can be bound in the same way using
:func:`class_::def_static`.

.. note::

Binding C++ types in unnamed namespaces (also known as anonymous namespaces)
works reliably only with GCC and MSVC, but not with CLANG, or if libc++ is used.
See `#4319 <https://github.com/pybind/pybind11/pull/4319>`_ for background.
If portability is a concern, it is therefore not recommended to bind C++
types in unnamed namespaces. It will be safest to manually pick unique
namespace names.

Keyword and default arguments
=============================
It is possible to specify keyword and default arguments using the syntax
Expand Down
4 changes: 2 additions & 2 deletions include/pybind11/detail/internals.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
/// further ABI-incompatible changes may be made before the ABI is officially
/// changed to the new version.
#ifndef PYBIND11_INTERNALS_VERSION
# define PYBIND11_INTERNALS_VERSION 4
# define PYBIND11_INTERNALS_VERSION 5
#endif

PYBIND11_NAMESPACE_BEGIN(PYBIND11_NAMESPACE)
Expand Down Expand Up @@ -114,7 +114,7 @@ inline void tls_replace_value(PYBIND11_TLS_KEY_REF key, void *value) {
// libstdc++, this doesn't happen: equality and the type_index hash are based on the type name,
// which works. If not under a known-good stl, provide our own name-based hash and equality
// functions that use the type name.
#if defined(__GLIBCXX__)
#if !defined(_LIBCPP_VERSION)
inline bool same_type(const std::type_info &lhs, const std::type_info &rhs) { return lhs == rhs; }
using type_hash = std::hash<std::type_index>;
using type_equal_to = std::equal_to<std::type_index>;
Expand Down
2 changes: 2 additions & 0 deletions tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ set(PYBIND11_TEST_FILES
test_tagbased_polymorphic
test_thread
test_union
test_unnamed_namespace_a
test_unnamed_namespace_b
test_virtual_functions)

# Invoking cmake with something like:
Expand Down
25 changes: 25 additions & 0 deletions tests/test_unnamed_namespace_a.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "pybind11_tests.h"

namespace {
struct any_struct {};
} // namespace

TEST_SUBMODULE(unnamed_namespace_a, m) {
if (py::detail::get_type_info(typeid(any_struct)) == nullptr) {
py::class_<any_struct>(m, "unnamed_namespace_a_any_struct");
} else {
m.attr("unnamed_namespace_a_any_struct") = py::none();
}
m.attr("defined___clang__") =
#if defined(__clang__)
true;
#else
false;
#endif
m.attr("defined__LIBCPP_VERSION") =
#if defined(_LIBCPP_VERSION)
true;
#else
false;
#endif
}
32 changes: 32 additions & 0 deletions tests/test_unnamed_namespace_a.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import pytest

from pybind11_tests import unnamed_namespace_a as m
from pybind11_tests import unnamed_namespace_b as mb


@pytest.mark.xfail(
"m.defined___clang__ or m.defined__LIBCPP_VERSION",
reason="Known issues: https://github.com/pybind/pybind11/pull/4319",
strict=False,
)
def test_have_class_any_struct():
assert m.unnamed_namespace_a_any_struct is not None


def test_have_at_least_one_class_any_struct():
assert (
m.unnamed_namespace_a_any_struct is not None
or mb.unnamed_namespace_b_any_struct is not None
)


@pytest.mark.xfail(
"m.defined___clang__ or m.defined__LIBCPP_VERSION",
reason="Known issues: https://github.com/pybind/pybind11/pull/4319",
strict=True,
)
def test_have_both_class_any_struct():
assert (
m.unnamed_namespace_a_any_struct is not None
and mb.unnamed_namespace_b_any_struct is not None
)
25 changes: 25 additions & 0 deletions tests/test_unnamed_namespace_b.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#include "pybind11_tests.h"

namespace {
struct any_struct {};
} // namespace

TEST_SUBMODULE(unnamed_namespace_b, m) {
if (py::detail::get_type_info(typeid(any_struct)) == nullptr) {
py::class_<any_struct>(m, "unnamed_namespace_b_any_struct");
} else {
m.attr("unnamed_namespace_b_any_struct") = py::none();
}
m.attr("defined___clang__") =
#if defined(__clang__)
true;
#else
false;
#endif
m.attr("defined__LIBCPP_VERSION") =
#if defined(_LIBCPP_VERSION)
true;
#else
false;
#endif
}
12 changes: 12 additions & 0 deletions tests/test_unnamed_namespace_b.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import pytest

from pybind11_tests import unnamed_namespace_b as m


@pytest.mark.xfail(
"m.defined___clang__ or m.defined__LIBCPP_VERSION",
reason="Known issues: https://github.com/pybind/pybind11/pull/4319",
strict=False,
)
def test_have_class_any_struct():
assert m.unnamed_namespace_b_any_struct is not None

0 comments on commit 5aa6093

Please sign in to comment.