mirror of
https://github.com/pybind/pybind11.git
synced 2026-03-14 20:27:47 +00:00
Allow module-local classes to be loaded externally
The main point of `py::module_local` is to make the C++ -> Python cast unique so that returning/casting a C++ instance is well-defined. Unfortunately it also makes loading unique, but this isn't particularly desirable: when an instance contains `Type` instance there's no reason it shouldn't be possible to pass that instance to a bound function taking a `Type` parameter, even if that function is in another module. This commit solves the issue by allowing foreign module (and global) type loaders have a chance to load the value if the local module loader fails. The implementation here does this by storing a module-local loading function in a capsule in the python type, which we can then call if the local (and possibly global, if the local type is masking a global type) version doesn't work.
This commit is contained in:
@@ -18,7 +18,7 @@ using NonLocal2 = LocalBase<2>;
|
||||
using LocalExternal = LocalBase<3>;
|
||||
/// Mixed: registered local first, then global
|
||||
using MixedLocalGlobal = LocalBase<4>;
|
||||
/// Mixed: global first, then local (which fails)
|
||||
/// Mixed: global first, then local
|
||||
using MixedGlobalLocal = LocalBase<5>;
|
||||
|
||||
using LocalVec = std::vector<LocalType>;
|
||||
@@ -29,6 +29,15 @@ using NonLocalVec2 = std::vector<NonLocal2>;
|
||||
using NonLocalMap = std::unordered_map<std::string, NonLocalType>;
|
||||
using NonLocalMap2 = std::unordered_map<std::string, uint8_t>;
|
||||
|
||||
PYBIND11_MAKE_OPAQUE(LocalVec);
|
||||
PYBIND11_MAKE_OPAQUE(LocalVec2);
|
||||
PYBIND11_MAKE_OPAQUE(LocalMap);
|
||||
PYBIND11_MAKE_OPAQUE(NonLocalVec);
|
||||
//PYBIND11_MAKE_OPAQUE(NonLocalVec2); // same type as LocalVec2
|
||||
PYBIND11_MAKE_OPAQUE(NonLocalMap);
|
||||
PYBIND11_MAKE_OPAQUE(NonLocalMap2);
|
||||
|
||||
|
||||
// Simple bindings (used with the above):
|
||||
template <typename T, int Adjust, typename... Args>
|
||||
py::class_<T> bind_local(Args && ...args) {
|
||||
@@ -36,3 +45,16 @@ py::class_<T> bind_local(Args && ...args) {
|
||||
.def(py::init<int>())
|
||||
.def("get", [](T &i) { return i.i + Adjust; });
|
||||
};
|
||||
|
||||
// Simulate a foreign library base class (to match the example in the docs):
|
||||
namespace pets {
|
||||
class Pet {
|
||||
public:
|
||||
Pet(std::string name) : name_(name) {}
|
||||
std::string name_;
|
||||
const std::string &name() { return name_; }
|
||||
};
|
||||
}
|
||||
|
||||
struct MixGL { int i; MixGL(int i) : i{i} {} };
|
||||
struct MixGL2 { int i; MixGL2(int i) : i{i} {} };
|
||||
|
||||
Reference in New Issue
Block a user