Skip to content
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

Import error for nested classes with the same name but in different scopes #2187

Closed
jslee02 opened this issue Apr 26, 2020 · 1 comment
Closed

Comments

@jslee02
Copy link

jslee02 commented Apr 26, 2020

Issue description

Not sure if this is a pybind11 problem or not, but it fails to import when there are nested classes with the same name but in different scopes.

The following code builds fine with no errors, but only import error happens. If the second "Option" (for Derived::Option) is renamed to something else, then the import error disappears.

I believe this binding code is legitimate because it works in equivalent Python code.

class Base:
    class Option:
        def __init__(self):
            print('Base.Option')

    def __init__(self):
        print('Base')


class Derived(Base):
    class Option(Base.Option):
        def __init__(self):
            print('Derived.Option')

    def __init__(self):
        print('Derived')


b = Base()
d = Derived()

o1 = Base.Option()
o2 = Derived.Option()

#---------
# Output:
#---------
# Base
# Derived
# Base.Option
# Derived.Option

Reproducible example code

  • compiler: GCC 9.2.1
  • pybind11: v2.5
  • Python: v3.5.2
#include <pybind11/pybind11.h>

class Base {
public:
  Base() = default;
  class Option {
  public:
    Option() = default;
  };
};

class Derived : public Base {
public:
  Derived() = default;
  class Option : public Base::Option {
  public:
    Option() = default;
  };
};

namespace py = pybind11;

PYBIND11_MODULE(example, m) {
  auto base = py::class_<Base>(m, "Base").def(py::init<>());
  py::class_<Base::Option>(base, "Option").def(py::init<>());

  auto derived = py::class_<Derived, Base>(m, "Derived").def(py::init<>());
  py::class_<Derived::Option, Base::Option>(derived, "Option").def(py::init<>());
}
Python 3.5.2 (default, Apr 16 2020, 17:47:17) 
[GCC 5.4.0 20160609] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import example
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: generic_type: cannot initialize type "Option": an object with that name is already defined
@YannickJadoul
Copy link
Collaborator

Duplicate of #1624. The problem is that pybind11 sees that hasattr(Derived, "Option") (namely in Base). Temporary (but ugly) workaround is the following:

  auto base = py::class_<Base>(m, "Base").def(py::init<>());
  auto derived = py::class_<Derived, Base>(m, "Derived").def(py::init<>());

  py::class_<Derived::Option, Base::Option>(derived, "Option").def(py::init<>());
  py::class_<Base::Option>(base, "Option").def(py::init<>());

I am thinking about/working on a fix. Closing this as duplicate; follow #1624 instead.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants