Có khá nhiều phạm vi để làm những việc hữu ích bằng cách sử dụng generic smart pointer support trong SWIG, bất chấp sự thiếu chú ý hỗ trợ trong C++ 11 ghi chú.
Tóm lại nếu có operator->
thì SWIG đã hợp nhất các thành viên của con trỏ vào con trỏ để cho phép chúng được sử dụng thay thế lẫn nhau trong ngôn ngữ đích trong một thời gian dài.
tôi đã đặt cùng một ví dụ đầy đủ về cách này có thể làm việc cho bạn, bằng cách sử dụng test.hh dụ tập tin Hader dưới đây:
#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();
}
Để sử dụng unique_ptr hợp lý bên trong Python tôi đã phải viết sau tập SWIG, 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
trong đó bao gồm đủ của một tập hợp con của định nghĩa của std::unique_ptr
có ích. (Bạn có thể thêm hoặc loại bỏ các hàm tạo phụ thuộc vào chính xác ngữ nghĩa bạn muốn trong Python, tôi đã bỏ qua các tùy chỉnh ở đây).
Nó cũng thêm macro wrap_unique_ptr
để thiết lập hỗ trợ. Sơ đồ trang web chỉ ép buộc mã được tạo ra của SWIG sử dụng hàm tạo di chuyển thay vì hàm tạo bản sao khi trả về theo giá trị.
Chúng ta có thể sử dụng nó theo cách sau:
%module test
%{
#include "test.hh"
%}
%include "std_unique_ptr.i"
wrap_unique_ptr(FooUniquePtr, Foobar);
%include "test.hh"
tôi đã xây dựng này với:
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
nào cho phép chúng ta sử dụng Python sau:
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)
ý rằng mặc dù là một số unique_ptr<Foobar>
, chúng tôi vẫn có thể nói a.baz()
và a.wibble
. Phương thức release()
cũng trả về một con trỏ 'thô' có thể sử dụng, được sở hữu bởi Python ngay bây giờ (vì nếu không nó sẽ không có chủ sở hữu). get()
trả về một con trỏ được mượn bên trong Python như bạn mong đợi.
Tùy thuộc vào cách bạn dự định sử dụng con trỏ, đây có thể là khởi đầu tốt cho các kiểu chữ của riêng bạn và sạch hơn so với %extend
và release()
ở mọi nơi bạn có unique_ptrs.
So với %shared_ptr
, điều này không sửa đổi trong các bản đồ và nó không thay đổi các nhà xây dựng theo cách tương tự như hỗ trợ shared_ptr. Đó là trách nhiệm của bạn để lựa chọn khi con trỏ thô trở thành unique_ptrs trong Python vẫn còn.
Tôi đã viết câu trả lời tương tự cho using std::weak_ptr
with SWIG trong khi quay lại.
Một trong những thứ có thể dễ dàng thêm vào để nâng cao điều này sẽ là một typemap cho 'Type *'/'Type &' có thể xử lý hoặc là một unique_ptr hoặc một con trỏ thực. – Flexo
Thú vị. Tôi đồng ý rằng điều này là sạch hơn nhiều so với việc trộn lẫn các tệp giao diện với các hàm bổ sung để xử lý các chuyển đổi giữa các con trỏ của unique_ptr và raw. Nó cũng cho thấy ý định sở hữu rõ ràng. Cảm ơn bạn đã trả lời chi tiết. – Homar
Lưu ý: Lớp của tôi có một 'std :: unique_ptr pImpl' riêng, trong trường hợp này tôi phải ** không ** bao gồm bất kỳ' wrap_unique_ptr (RealImplUniquePtr, RealImpl) '(có thể cung cấp lỗi về' kiểu không đầy đủ' từ ' default_delete'), chỉ cần bọc các loại có sẵn hoàn toàn từ API công khai. –
unhammer