Skip to content

[BUG]: make_iterator causes runtime error in second scoped_interpreter #3776

Open
@jasjuang

Description

@jasjuang

Required prerequisites

Problem description

This issue is similar to #2101, the reported minimal example problem in #2101 is fixed in the latest master because of #3744. However, the below minimal example will produce the error

1
2
3
terminate called after throwing an instance of 'pybind11::error_already_set'
  what():  RuntimeError: instance allocation failed: new instance has no pybind11-registered base types

At:
  <string>(4): <module>

Aborted (core dumped)

I can reproduce this problem in Ubuntu and macOS.

The real use case is that each gtest TEST block will have its own py::scoped_interpreter, and this bug is preventing me from writing for i in testclass: more than once, but I would like to write for i in testclass: in multiple different TEST blocks.

Reproducible example code

CMakeLists.txt

cmake_minimum_required(VERSION 3.20)
project(pybindsample)

set(pybind11_DIR "/home/jasjuang/install/share/cmake/pybind11")
find_package(pybind11 REQUIRED)

pybind11_add_module(${PROJECT_NAME} pybindsample.cpp)
target_compile_features(${PROJECT_NAME} PUBLIC cxx_std_17)

add_executable(pybindsample_test pybindsample_test.cpp)
target_link_libraries(pybindsample_test pybind11::module pybind11::embed)

pybindsample.cpp

#include "pybind11/pybind11.h"
#include "pybind11/stl.h"

namespace py = pybind11;

class TestClass {
public:
  TestClass() = default;
  std::vector<int>::iterator begin() noexcept { return vec.begin(); }
  std::vector<int>::iterator end() noexcept { return vec.end(); }

private:
  std::vector<int> vec = {1, 2, 3};
};

PYBIND11_MODULE(pybindsample, m) {
  py::class_<TestClass>(m, "TestClass")
      .def(py::init<>())
      .def(
          "__iter__",
          [](TestClass &t) { return py::make_iterator(t.begin(), t.end()); },
          py::keep_alive<0, 1>());
}

pybindsample_test.cpp

#include "pybind11/embed.h"
#include "pybind11/pybind11.h"
#include "pybind11/stl.h"

namespace py = pybind11;

int main() {
  {
    py::scoped_interpreter g;
    py::eval<py::eval_statements>("import pybindsample\n"
                                  "testclass=pybindsample.TestClass()\n"
                                  "for i in testclass:\n"
                                  "    print(i)\n");
  }
  {
    py::scoped_interpreter g;
    py::eval<py::eval_statements>("import pybindsample\n"
                                  "testclass=pybindsample.TestClass()\n"
                                  "for i in testclass:\n"
                                  "    print(i)\n");
  }

  return 0;
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions