Swig Python Wrap C ++ Вектор указателей на полиморфные типы - PullRequest
0 голосов
/ 03 марта 2019

У меня есть 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 Ответ

0 голосов
/ 04 марта 2019

Вы почти там ...

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();
};

entity.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;
}

entity.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 в вектор должно быть простым.

...