swig python wrap c++​​ 指向多态类型的指针向量

Posted

技术标签:

【中文标题】swig python wrap c++​​ 指向多态类型的指针向量【英文标题】:swig python wrap c++ vector of pointers to polymorphic types 【发布时间】:2019-03-02 21:08:08 【问题描述】:

我有 2 个类(“Foo”、“Bar”),它们是从基类“Base”派生的,如下所示。

class Base
public:
    virtual void basemethod() = 0 ;
;

class Base: public Foo

    virtual void basemethod() ;
    void foo();
;

class Base: public Bar
    virtual void basemethod() ;
    void bar();
;

还有另一个类创建了这些类的实例,如下所示

class Entity
    std::vector<std::shared_ptr<Base> > Get();
;

我有下面的 idl 文件,但在这种情况下,在 python 代码中,我无法访问真实的类型信息

%include "std_vector.i"
%include <std_shared_ptr.i>

%template(MyVector) std::vector<std::shared_ptr<Base> >;

是否可以将此接口包装在 swig 中,以便下面的 python 代码按预期工作?

entity = Entity()
vec = entity.Get()

if isinstance(vec[0], Bar):
    print("this is a Bar!")

if isinstance(vec[1], Foo):
    print("this is a Foo!")

【问题讨论】:

【参考方案1】:

你快到了……

base.hpp

#pragma once

class Base
 public:
  virtual void basemethod() = 0;
  virtual ~Base() = default;
  virtual const char* name() = 0;
;

衍生物.hpp

#pragma once

#include "base.hpp"

class Foo : public Base 
  virtual void basemethod();
  void foo();
  const char* name();
;

class Bar : public Base 
  virtual void basemethod();
  void bar();
  const char* name();
;

实体.hpp

#include <memory>
#include <vector>
#include "base.hpp"

class Entity 
 public:
  static std::vector<std::shared_ptr<Base> > Get();
;

衍生物.cpp

#include "derivatives.hpp"

void Foo::basemethod() 

void Foo::foo() 


const char* Foo::name() 
  static char name[] = "Foo";
  return name;


void Bar::basemethod() 

void Bar::bar() 


const char* Bar::name() 
  static char name[] = "Bar";
  return name;

实体.cpp

#include "entity.hpp"
#include "derivatives.hpp"

std::vector<std::shared_ptr<Base> > Entity::Get() 
    std::vector<std::shared_ptr<Base> > vec;
    std::shared_ptr<Base> base = std::make_shared<Foo>();
    vec.push_back(base);
    return vec;

example.i

%module example
%
  #include "base.hpp"
  #include "derivatives.hpp"
  #include "entity.hpp"
%

%include "std_vector.i"
%include "std_shared_ptr.i"

%shared_ptr(Base);
%shared_ptr(Foo);
%shared_ptr(Bar);

%template(BaseVector) std::vector<std::shared_ptr<Base> >;

%include "base.hpp"
%include "derivatives.hpp"
%include "entity.hpp"

%extend Base 
%pythoncode %
  def __instancecheck__(self, other):
    return self.name() == other.name()
%
;

编译完成后,可以在Python中进行如下操作

import example
hmm = example.Entity_Get()
isinstance(hmm[0], example.Foo())

Bar 类的条目添加到向量应该是直截了当的。

【讨论】:

以上是关于swig python wrap c++​​ 指向多态类型的指针向量的主要内容,如果未能解决你的问题,请参考以下文章

指向 swig(或 Boost::Python)中的成员的指针

Swig:将成员变量(指向值的指针)转换为 python 列表

从 SWIGged Python 中的 C++ 基类派生

如何为 Python Swigged C++ 对象创建和分配回调函数

SWIG包装器未声明(此功能首次使用)

错误 C2062:类型 int 意外