Pybind11:在构造上将类所有权转移到 C++ [英] Pybind11: Transfer Class Ownership to C++ on Construct

查看:38
本文介绍了Pybind11:在构造上将类所有权转移到 C++的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我遇到了一个问题,即使用 pybind11 从 c++ 基类派生的 python 类被立即销毁(垃圾收集).我希望 C++ 拥有动态分配的对象的所有权,但我似乎无法做到这一点.我试过 keep_alive,将 shared_ptr<> 作为 py::class_ 模板参数传递,而 py::return_value_policy ... 没有任何效果.我怀疑这只是用户错误.

I'm having an issue where a python class, which is derived from a c++ base class using pybind11, is being immediately destructed (garbage collected). I would like C++ to take ownership of the dynamically allocated object, but I can't seem to make that happen. I've tried keep_alive, passing shared_ptr<> as py::class_ template argument, and py::return_value_policy... nothing is working. I suspect this is just user error.

这是对我遇到的实际问题的简化,代码库的架构类似.改变架构不是一个选项,所以让这个示例工作对我来说至关重要.

This is a simplification of the real issue I'm having with a much larger code base that is architected similarly. Changing the architecture is not an option, so making this example work is critical for me.

我有两个 C++ 类,我为使用 pybind11 创建了 python 接口.A类和B类都有虚方法,所以有对应的trampoline类来支持继承.用户调用 B::Run() 函数,这会导致创建一个动态分配的(通过新的)A 对象.当我在 python 中创建这两个类的特化时,如下所示......分段错误,因为 B::aBase 在 B::Run 被调用后立即被销毁.

I have two c++ classes that I have created python interfaces for using pybind11. Class A and B both have virtual methods, so they have corresponding trampoline classes to support inheritance. The user calls the B::Run() function which results in a dynamically allocated (via new) A object to be created. When I create specializations of these two classes in python, as shown below.... Segmentation fault because the B::aBase is destroyed immediately after B::Run being called.

任何想法如何解决这个问题?提前致谢!

Any Ideas how to fix this? Thanks in advance!

class A
{
public:
    A(){};
    virtual ~A()
    {
        std::cout << "In A::~A()\n";
    };

    virtual char* SayHello()
    {
        char* x = "\n\nHello from Class A\n\n";
        return x;
    }
};

class ATramploline : public A
{
public:
    using A::A;
    char* SayHello() override
    {
        PYBIND11_OVERLOAD( char*,A,SayHello,);
    }
};


class B
{
public:
    B()
    {
        std::cout << "In Class B Constructor\n";
    }

    void Run()
    {
        aBase = AllocateAnAClass();
        std::cout << aBase->SayHello();
    }

    virtual ~B()
    {
        fprintf(stderr,"About to delete aBase");
        delete aBase;
    }

    A* aBase;

    virtual A* AllocateAnAClass()
    {
        return new A;
    }
};

class BTramploline : public B
{
public:
    using B::B;
    A* AllocateAnAClass() override
    {
        PYBIND11_OVERLOAD( A*,B,AllocateAnAClass,);
    }
};

PYBIND11_MODULE(TestModule,m)
{
    py::class_<A,ATramploline>(m,"A")
        .def(py::init<>(),py::return_value_policy::reference_internal)
        .def("SayHello",&A::SayHello);

    py::class_<B,BTramploline>(m,"B")
        .def(py::init<>())
        .def("Run",&B::Run)
        .def("AllocateAnAClass",&B::AllocateAnAClass,py::return_value_policy::reference_internal);
}



#!/usr/bin/python3

from TestModule import A,B
class MyA(A):
    def __init__(self):
        super().__init__()
        print("Done with MyA Constructor")

    def SayHello(self):
        return '\n\nHello from Class MyA\n\n'

class MyB(B):
    def __init__(self):
        super().__init__()
        print("Done With MyB Constructor")
    def AllocateAnAClass(self):
        print("In MyB::AllocateAnAClass!!!")
        return MyA()

#x = B()
#x.Run()

y = MyB()
y.Run()

print("done with test script\n")

推荐答案

py::nodelete 是解决方案.虽然 n.m 的答案确实有效,但它需要返回并将现有库中的所有指针更改为智能指针,这对我来说不是一个可行的选择.使用 py::nodelete 允许我在 pybind11 端做所有事情.

py::nodelete was the solution. While n.m's answer DOES work, it would require going back and chaning all of the pointer in an existing libary to smart pointers, which isn't a viable option for me. Using py::nodelete allows me to do everything on the pybind11 side.

py::class_<A,ATramploline,std::unique_ptr<A,py::nodelete> >(m,"A")
        .def(py::init<>())
        .def("SayHello",&A::SayHello);

这篇关于Pybind11:在构造上将类所有权转移到 C++的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆