pybind / pybind/pybind11

[BUG]: send a python function to c++ as a std::function to create Python subclass instance,the constructor of python class be called but the instance still the base class

Open
#4,712 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

triage
Dominant language
C++
Stars
18k
Forks
2.3k
Avg merge
5d 17h
Merged PRs (30d)
10

Description

Required prerequisites
What version (or hash if on master) of pybind11 are you using?

2.10.4

Problem description
  • my cpp code
class Pet {
public:
    Pet()
    {
        id = makePetId();
        printf("Pet::Pet\n");
    }
    virtual ~Pet() { printf("Pet::~Pet\n"); }
    Pet(const Pet&) = delete;
    Pet(const Pet&&) = delete;

    virtual std::string name() const { return "pet"; }
    static int makePetId()
    {
        static int id = 0;
        return id++;
    }

    int id = -1;
};

class PyPet : public Pet {
public:
    using Pet::Pet;
    std::string name() const override { PYBIND11_OVERRIDE(std::string, Pet, name, ); }
};

class PetRoom {
public:
    PetRoom() = default;
    void echoPetName(std::shared_ptr<Pet> pet) { printf("pet name: %s\n", pet->name().c_str()); }
    void addPet(std::shared_ptr<Pet> pet)
    {
        printf("add pet: %s\n", pet->name().c_str());
        pets.push_back(pet);
    }
    void addPetCustom(std::function<std::shared_ptr<Pet>()> petGenerator)
    {
        auto pet = petGenerator();
        printf("add pet custom: %s\n", pet->name().c_str());
        pets.push_back(pet);
    }
    std::vector<std::shared_ptr<Pet>> pets;
};

py::class_<Pet, PyPet, std::shared_ptr<Pet>>(m, "Pet")
    .def(py::init<>()).def("name", &Pet::name)
    .def_readonly("id", &PyPet::id);

py::class_<PetRoom>(m, "PetRoom")
    .def(py::init<>())
    .def("echoPetName", &PetRoom::echoPetName)
    .def("addPet", &PetRoom::addPet)
    .def("addPetCustom", &PetRoom::addPetCustom)
    // .def_readwrite("pets", &PetRoom::pets);
    .def_readwrite("pets", &PetRoom::pets, py::return_value_policy::reference);

  • my python code
import libpybind
import unittest

class Dog(libpybind.Pet):
    @staticmethod
    def create():
        print("create python dog")
        return Dog()

    def __init__(self):
        print("construct python dog")
        libpybind.Pet.__init__(self)

    def name(self):
        return "dog"

class TestClass(unittest.TestCase):
    def setUp(self):
        self.petRoom = libpybind.PetRoom()
        return super().setUp()

    def test_if_functional_right(self):
        # self.skipTest("skip test_if_functional_right")
        self.petRoom.addPetCustom(Dog.create)
        for pet in self.petRoom.pets:
            print("name={},id={}".format(pet.name(), pet.id))

if __name__ == "__main__":
    unittest.main()
  • result
create python dog
construct python dog
Pet::Pet
add pet custom: pet
name=pet,id=0
.Pet::~Pet
  • my problem
    • I use a std::function to create std::shared_ptr,because I want to create python subclass in python
    • I send the Dog.create to the PetRoom.addPetCustom
    • The Dog.create been called in PetRoom.addPetCustom,but the result shows the inst is still Pet not Dog
Reproducible example code

No response

Is this a regression? Put the last known working version here if it is.

Not a regression

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the PetRoom.addPetCustom binding and the Dog.create callback shown in the issue, then trace how the returned shared_ptr is converted and stored in PetRoom.pets. Reproduce the example and compare the resulting object's type and name() dispatch; done means the stored object remains the Python Dog subclass and reports "dog" rather than "pet".

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp, python
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.