범위를 꽤 많이는 C++ 11 노트 지원의주의 부족에도 불구하고, SWIG의 generic smart pointer support을 사용하여 유용한 일을 할 수있다.
간단히 말해서 operator->
이있는 경우 SWIG는 pointee 멤버를 포인터로 병합하여 오랜 시간 동안 대상 언어 내에서 상호 교환 할 수있게 사용합니다.
내가 함께이 아래의 예 hader 파일 test.hh을 사용하여, 당신을 위해 작동하는 방법의 전체 예제를 넣어했습니다 내가 써야했다 파이썬 내부 현명 unique_ptr을 사용하려면
#include <memory>
#include <iostream>
struct Foobar {
void baz() { std::cout << "This works\n"; }
int wibble;
};
std::unique_ptr<Foobar> make_example() {
return std::unique_ptr<Foobar>(new Foobar);
}
void dump_example(const std::unique_ptr<Foobar>& in) {
std::cout << in->wibble << "\n";
in->baz();
}
다음 꿀꺽 꿀꺽 파일, std_unique_ptr.i :
namespace std {
%feature("novaluewrapper") unique_ptr;
template <typename Type>
struct unique_ptr {
typedef Type* pointer;
explicit unique_ptr(pointer Ptr);
unique_ptr (unique_ptr&& Right);
template<class Type2, Class Del2> unique_ptr(unique_ptr<Type2, Del2>&& Right);
unique_ptr(const unique_ptr& Right) = delete;
pointer operator->() const;
pointer release();
void reset (pointer __p=pointer());
void swap (unique_ptr &__u);
pointer get() const;
operator bool() const;
~unique_ptr();
};
}
%define wrap_unique_ptr(Name, Type)
%template(Name) std::unique_ptr<Type>;
%newobject std::unique_ptr<Type>::release;
%typemap(out) std::unique_ptr<Type> %{
$result = SWIG_NewPointerObj(new $1_ltype(std::move($1)), $&1_descriptor, SWIG_POINTER_OWN);
%}
%enddef
std::unique_ptr
의 정의의 부분 집합을 충분히 포함 유용합니다. (파이썬에서 원하는 의미론에 따라 생성자를 추가하거나 제거 할 수 있습니다. 여기에서 사용자 정의 삭제자를 간과했습니다.)
또한 지원을 설정하는 매크로 wrap_unique_ptr
을 추가합니다. typemap은 값으로 반환 할 때 SWIG의 생성 된 코드가 복사 생성자 대신 이동 생성자를 사용하도록합니다.
우리는 다음과 같은 방법으로 사용할 수 있습니다 : 다음 파이썬 사용할 수있게 해준다
swig3.0 -py3 -c++ -python -Wall test.i
g++ -Wall -Wextra -Wno-missing-field-initializers test_wrap.cxx -std=c++11 -I/usr/include/python3.4/ -lpython3.4m -shared -o _test.so
:
%module test
%{
#include "test.hh"
%}
%include "std_unique_ptr.i"
wrap_unique_ptr(FooUniquePtr, Foobar);
%include "test.hh"
내가 이것을 내장
from test import *
a = make_example()
print(a)
a.wibble = 1234567
a.baz()
dump_example(a)
a.baz()
print(bool(a))
print(bool(FooUniquePtr(None)))
b=a.release()
print(b)
공지 사항을 그 unique_ptr<Foobar>
에도 불구하고 우리는 여전히 a.baz()
과 a.wibble
을 말할 수 있습니다. release()
메서드는 또한 파이썬이 현재 소유하고있는 사용 가능한 '원시'포인터를 반환합니다. 그렇지 않으면 소유자가 없으므로 사용할 수 있습니다. get()
은 예상대로 Python에서 빌린 포인터를 반환합니다.
포인터를 어떻게 사용 하느냐에 따라 unique_ptrs가있는 모든 곳의 %extend
및 release()
보다 자신의 typemaps 및 클리너에 대한 유용한 시작이 될 것입니다.
%shared_ptr
과 비교하여 typemap을 수정하지 않으며 shared_ptr 지원과 동일한 방법으로 생성자를 변경하지 않습니다. 원시 포인터가 파이썬 안에서 여전히 unique_ptrs가 될 때를 선택하는 것은 당신의 책임입니다.
나는 using std::weak_ptr
with SWIG에 대해 비슷한 답변을 작성했습니다.
향상시키기 위해 추가하기 쉬운 사항 중 하나는 typemap unique_ptr이나 실수 포인터를 처리 할 수있는'Type *'/'Type &'에 대해. – Flexo
흥미 롭습니다. unique_ptr과 raw 포인터 사이의 변환을 처리하는 추가 함수로 인터페이스 파일을 muddying하는 것보다 훨씬 깔끔하다는 것에 동의합니다. 또한 명확한 소유권을 나타냅니다. 상세한 답변을 해줘서 고맙습니다. – Homar
참고 : 클래스에는 개인 std :: unique_ptr pImpl'이 있습니다.이 경우에는'wrap_unique_ptr (RealImplUniquePtr, RealImpl)'을 포함하지 않아야합니다. (''불완전한 타입' default_delete'), 공용 API에서 완전히 사용할 수있는 유형을 랩핑하면됩니다. –
unhammer