简体   繁体   English

Boost.Python包装原始指针但公开方法

[英]Boost.Python wrap raw pointer but expose methods

I have a class with methods that I get raw pointers to: 我有一个类,其中的方法可以获取原始的指针:

struct Foo {
    int getSomething() const { .. }
    void setSomethingElse(int ) { .. }
    // .. lots more getters, setters, and other methods ..
};

Foo* p = make_something();

I had originally exposed this directly to python: 我最初将其直接暴露给python:

py::class_<Foo, Foo*, boost::noncopyable>("Foo", py::no_init)
    .def("getSomething", &Foo::getSomething)
    // ..
;

But the Foo s I get come from an allocator that aggressively reuses memory, and my usage in python might hold onto these Foo* s longer than they actually exist as valid objects in C++. 但是我得到的Foo来自积极地重用内存的分配器,而我在python中的使用可能会使这些Foo*保持的时间比它们在C ++中实际存在的时间长。 So really I want to wrap them to save off some values, eg: 所以我真的想包装它们以节省一些值,例如:

struct FooWrapper {
    Foo* p;
    int val1;

    FooWrapper(Foo* p) : p(p), val1(p->getVal1()) { }

    operator Foo*() const { return p; }
    int getVal1() const { return val1; }
};

FooWrapper fw(make_something());

But now in order to use the healthy number of functions of Foo , I have to copy a whole bunch of stuff into FooWrapper . 但是现在为了使用健康Foo功能,我必须将一堆东西复制到FooWrapper Or do I?? 还是我?? Is there a way to write and expose FooWrapper such that getVal1() calls fw.getVal1() but any other function calls fw.p->getSomethingElse() in a way that I can avoid copying every other method on Foo ? 有没有一种方法可以编写和公开FooWrapper ,使得getVal1()调用fw.getVal1()但其他函数调用fw.p->getSomethingElse()可以避免在Foo上复制其他所有方法? This is python after all, so I'm guessing there's something I can do with getattr ? 毕竟这是python,所以我猜我可以用getattr做些什么?

This was easier than I'd expected: 这比我预期的要容易:

struct FooWrapper 
{
    // as before

    static py::object getattr(py::object self, std::string attr)
    {
        FooWrapper& fw = py::extract<FooWrapper&>(self);
        return py::getattr(py::object{py::ptr(fw.p)}, attr.c_str());
    }
};

With: 附:

py::class_<FooWrapper, boost::noncopyable>("Foo", py::no_init)
    .def("getVal1", &FooWrapper::getVal1)
    .def("getSomethingElse", &FooWrapper::getSomethingElse)
    // ..
    // and, finally, for everything else:
    .def("__getattr__", &FooWrapper::getattr) 
;

In python then: 然后在python中:

>>> f = get_foo() # this is really a FooWrapper
>>> f.getVal1
<bound method FooWrapper.getVal1 of <Test.FooWrapper object at 0x7faacd8d48e8>>
>>> f.getVal2
<bound method Foo.getVal2 of <Test.Foo object at 0x7faacd8d6210>>
>>> f.getVal3
AttributeError: 'Foo' object has no attribute 'getV3'

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM