首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何用SWIG处理唯一的ptr

如何用SWIG处理唯一的ptr
EN

Stack Overflow用户
提问于 2014-12-29 18:05:12
回答 4查看 5K关注 0票数 10

我有一个实现发布-订阅模式的EventDispatcher类。它的界面看起来像这样(简化):

代码语言:javascript
运行
复制
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;
}

我想将这个类公开给Python。最新的SWIG文档指出:

目前还没有针对std::weak_ptr和std::unique_ptr的特殊智能指针处理。

我非常希望至少能够在c++端继续使用unique_ptr。我有什么选择?

我考虑使用SWIG的%extend特性扩展类,但是我无法使用这种方法访问私有成员(m_subscriptions)。

我看到的唯一其他选项是使用SWIG预处理器来定义额外的方法,swig_publishswig_subscribe,但这使我的接口文件混乱不堪。

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2014-12-30 04:42:21

在SWIG中使用通用智能指针支持可以做很多有用的事情,尽管C++11注释中指出缺乏支持。

简而言之,如果有一个operator->,那么SWIG已经将切入点的成员合并到指针中,允许它们在目标语言中互换使用很长一段时间。

使用下面的示例hader文件test.hh,我已经为您提供了一个完整的示例,说明了它是如何工作的:

代码语言:javascript
运行
复制
#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();
}

为了在Python中明智地使用unique_ptr,我必须编写以下std_unique_ptr.i文件:

代码语言:javascript
运行
复制
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定义的足够多的子集,因此是有用的。(您可以添加或删除构造函数,具体取决于Python中的语义,我忽略了这里的自定义删除器)。

它还添加了一个设置支持的宏wrap_unique_ptr。在按值返回时,类型地图只是强制SWIG生成的代码使用移动构造函数而不是复制构造函数。

我们可以通过以下方式使用它:

代码语言:javascript
运行
复制
%module test

%{
#include "test.hh"
%}

%include "std_unique_ptr.i"

wrap_unique_ptr(FooUniquePtr, Foobar);

%include "test.hh"

我用:

代码语言:javascript
运行
复制
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 

它允许我们使用以下Python:

代码语言:javascript
运行
复制
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.wibblerelease()方法还返回一个可用的“raw”指针,该指针现在属于Python (否则它将没有所有者)。正如您所期望的那样,get()在Python中返回一个借来的指针。

取决于您计划如何使用指针,这可能是您自己的类型地图的一个好的开端,并且比任何地方都有%extendrelease()的unique_ptrs更干净。

%shared_ptr相比,这不会修改类型映射,也不会像shared_ptr支持的那样更改构造函数。在Python中选择原始指针何时成为unique_ptrs是您的责任。

不久前,我为大口写了一个类似的答案。

票数 19
EN

Stack Overflow用户

发布于 2014-12-29 18:58:29

奇怪的是,似乎可以%ignore一个函数,%extend类定义一个被忽略的函数的替代实现,最后从该函数的替代实现中调用最初被忽略的函数。例如:

代码语言:javascript
运行
复制
%ignore EventDispatcher::subscribe(const std::string&, std::unique_ptr<Callback>);

%include "EventDispatcher.hpp"

%extend suborbital::EventDispatcher
{
    EventSubscription* EventDispatcher::subscribe(const std::string& event_name, PyObject* callback)
    {
        std::unique_ptr<Callback> callback_ptr(new Callback(callback));
        return $self->subscribe(event_name, std::move(callback_ptr)).release();
    }
}
票数 3
EN

Stack Overflow用户

发布于 2022-11-11 06:45:43

SWIG-4.1已经添加了std::unique_ptr支持。ptr的文档。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27693812

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档