Как использовать weak_ptr в swig?

На домашней странице SWIG говорится, что shared_ptr обрабатывается особым образом, а weak_ptr — нет. Означает ли это, что поддержка weak_ptr имеет какую-то ошибку/проблему в SWIG? Если это нормально использовать, как его использовать? Кто-нибудь может дать пример кода .i? Спасибо большое.


person wizardlee    schedule 17.07.2014    source источник


Ответы (1)


weak_ptr для использования не требуется никакой специальной поддержки в SWIG.

Операции, которые нуждаются в специальной поддержке в SWIG для shared_ptr, — это разыменование и передача в функции. Это потому, что вы никогда напрямую не разыменовываете и не создаете weak_ptr. Вместо этого, когда вы обычно используете его в C++, вы должны вызвать функцию-член lock(), чтобы обновить его до полного, сохраненного shared_ptr, или одну из других функций для запроса его состояния.

Таким образом, все, что вам нужно сделать на практике, это обернуть weak_ptr, как любой другой шаблон, и использовать существующую поддержку shared_ptr в сочетании. Например:

%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>;

Это можно реализовать с помощью 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);
  }
}

При запуске это дает:

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

(Обратите внимание, что System.gc() была полностью проигнорирована моей средой выполнения, поэтому попытка снова заблокировать действительно удалась)

Но он также работает с тем же файлом .i для следующего 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

И при запуске дает:

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

Где подсчет ссылок вместо GC приводит к сбою вызова lock() после того, как у последнего shared_ptr больше нет ссылок.

person Flexo    schedule 22.07.2014