How to use weak_ptr in swig?

前端 未结 1 601
感动是毒
感动是毒 2021-01-06 04:13

SWIG homepage says shared_ptr is specially handled, but weak_ptr not. Does it means weak_ptr supporting has some bug/issue in SWIG? If it\'s ok to use, how to use it? Can an

相关标签:
1条回答
  • 2021-01-06 04:52

    weak_ptr doesn't need any special support in SWIG to use.

    The operations that need special support in SWIG for shared_ptr are dereferencing and passing into functions. This is because you never directly dereference or create a weak_ptr. Instead when you're using it normally in C++ you would call the lock() member function to upgrade it to a full, retained shared_ptr or one of the other functions to query its state.

    So all you need to do in practice therefore is wrap weak_ptr like any other template and use the existing shared_ptr support in conjunction. For example:

    %module test
    
    %{
    #include <memory>
    %}
    
    %include <std_shared_ptr.i>
    
    %shared_ptr(Foo)
    
    namespace std {
    template<class Ty> class weak_ptr {
    public:
        typedef Ty element_type;
    
        weak_ptr();
        weak_ptr(const weak_ptr&);
        template<class Other>
            weak_ptr(const weak_ptr<Other>&);
        template<class Other>
            weak_ptr(const shared_ptr<Other>&);
    
        weak_ptr(const shared_ptr<Ty>&);
    
    
        void swap(weak_ptr&);
        void reset();
    
        long use_count() const;
        bool expired() const;
        shared_ptr<Ty> lock() const;
    };
    }
    
    %inline %{
        struct Foo { };
    %}
    %template(FooWeakPtr) std::weak_ptr<Foo>;
    

    This can be exercised with some Java:

    public class run {
      public static void main(String[] argv) {
        System.loadLibrary("test");
    
        Foo a = new Foo();
        System.out.println(a);
    
        FooWeakPtr b=new FooWeakPtr(a);
        System.out.println(b);
    
        Foo c=b.lock();
        System.out.println(c);
    
        System.out.println(b.use_count());
        a=null;
        System.gc();
        System.out.println(b.use_count());
        c=null;
        System.gc();
        System.out.println(b.use_count());
    
        Foo d=b.lock();
        System.out.println(d);
      }
    }
    

    When run this gives:

    swig2.0 -c++ -Wall -java test.i && g++ -Wall -Wextra -I/usr/lib/jvm/java-6-sun/include -I/usr/lib/jvm/java-6-sun/include/linux -std=c++0x -shared -o libtest.so test_wrap.cxx && javac run.java && LD_LIBRARY_PATH=. java run
    Foo@42719c
    FooWeakPtr@119298d
    Foo@f72617
    2
    2
    2
    Foo@dc8569
    

    (Notice here that System.gc() has been completely ignored by my runtime, so the attempt to lock again does actually succeed)

    But it also works with the same .i file for the following Python:

    import test
    
    a=test.Foo()
    print a
    
    b=test.FooWeakPtr(a)
    print b
    
    c=b.lock()
    print c
    
    print b.use_count()
    a=None
    print b.use_count()
    c=None
    print b.use_count()
    
    d=b.lock()
    print d
    

    And when run gives:

    g++ -Wall -Wextra -I/usr/include/python2.6 -std=c++0x -shared -o _test.so test_wrap.cxx && python run.py
    <test.Foo; proxy of <Swig Object of type 'std::shared_ptr< Foo > *' at 0xf7419710> >
    <test.FooWeakPtr; proxy of <Swig Object of type 'std::weak_ptr< Foo > *' at 0xf7419728> >
    <test.Foo; proxy of <Swig Object of type 'std::shared_ptr< Foo > *' at 0xf7419740> >
    2
    1
    0
    None
    

    Where the reference counting instead of GC does result in the call to lock() failing after the last shared_ptr has no more references.

    0 讨论(0)
提交回复
热议问题