我有一个EventDispatcher实现发布 - 订阅模式的类.它的界面看起来像这样(简化):
class EventDispatcher
{
public:
void publish(const std::string& event_name, std::unique_ptr<Event> event);
std::unique_ptr<Subscription> subscribe(const std::string& event_name, std::unique_ptr<Callback> callback);
private:
std::unordered_map<std::string, std::vector<std::unique_ptr<Callback>>> m_subscriptions;
}
Run Code Online (Sandbox Code Playgroud)
我想将这个类暴露给Python.最新的SWIG文档指出:
std :: weak_ptr和std :: unique_ptr还没有特殊的智能指针处理.
我非常希望至少能够在c ++方面继续使用unique_ptr.我有什么选择?
我考虑使用SWIG的%扩展功能扩展类,但我无法m_subscriptions使用此方法访问私有成员().
唯一的其他选择,我可以看到的是使用SWIG预处理器定义额外的方法,swig_publish并且swig_subscribe,但这杂波我的接口文件.
Fle*_*exo 16
尽管在C++ 11笔记中缺乏支持,但使用SWIG中的通用智能指针支持可以做很多有用的事情.
简而言之,如果有一个,operator->那么SWIG已经将指针对象的成员合并到指针中,以允许它们在目标语言中长时间互换使用.
我已经使用下面的示例hader文件test.hh汇总了一个完整的示例,说明这可能对您有用:
#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();
}
Run Code Online (Sandbox Code Playgroud)
为了在Python内部明智地使用unique_ptr,我必须编写以下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
Run Code Online (Sandbox Code Playgroud)
其中包含足够的定义的子集std::unique_ptr是有用的.(您可以添加或删除构造函数,具体取决于您在Python中确切的语义,我忽略了自定义删除器).
它还添加了一个wrap_unique_ptr设置支持的宏.类型映射只是强制SWIG生成的代码在按值返回时使用移动构造函数而不是复制构造函数.
我们可以通过以下方式使用它:
%module test
%{
#include "test.hh"
%}
%include "std_unique_ptr.i"
wrap_unique_ptr(FooUniquePtr, Foobar);
%include "test.hh"
Run Code Online (Sandbox Code Playgroud)
我建立了这个:
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
Run Code Online (Sandbox Code Playgroud)
这允许我们使用以下Python:
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)
Run Code Online (Sandbox Code Playgroud)
请注意,尽管unique_ptr<Foobar>我们仍然可以说a.baz()和a.wibble.该release()方法还返回一个可用的"原始"指针,该指针现在归Python所有(否则它不会拥有所有者).get()如你所料,在Python中返回一个借来的指针.
根据您相当打算如何使用指针这可能是一个良好的开端为自己的typemaps比一个更清洁%extend和release()无处不在,你有unique_ptrs.
相比之下%shared_ptr,这不会修改in类型映射,也不会像shared_ptr支持那样更改构造函数.当你的原始指针在Python中成为unique_ptrs时,你有责任选择它.
我写了一篇与SWIG一起使用std::weak_ptr的类似答案.
| 归档时间: |
|
| 查看次数: |
3010 次 |
| 最近记录: |