Общие указатели и сборка в SIP4 (было: Динамическое приведение в SWIG / python?) - PullRequest
3 голосов
/ 10 июля 2010

Так что я играю с Python, C ++ 0x и SWIG 2.0. У меня есть заголовок, который выглядит так:

#include <string>
#include <iostream>
#include <memory>
using namespace std;

struct Base {
  virtual string name();
  int foo;
  shared_ptr<Base> mine;
  Base(int);  
  virtual ~Base() {}
  virtual void doit(shared_ptr<Base> b) {
    cout << name() << " doing it to " << b->name() << endl;
    mine = b;
  }
  virtual shared_ptr<Base> getit() {
    return mine;
  }
};

struct Derived : Base {
  virtual string name();
  int bar;
  Derived(int, int);
};

Между тем, файл интерфейса выглядит так:

%module(directors="1") foo
%feature("director");

%include <std_string.i>

%include <std_shared_ptr.i>
%shared_ptr(Base)
%shared_ptr(Derived)

%{
#define SWIG_FILE_WITH_INIT
#include "foo.hpp"
%}

%include "foo.hpp"

Мой сеанс Python выглядит так:

>>> import foo
>>> b = foo.Base(42)
>>> d = foo.Derived(23,64)
>>> b.doit(d)
Base doing it to Derived 
>>> g = b.getit()
>>> g
<foo.Base; proxy of <Swig Object of type 'std::shared_ptr< Base > *' at 0x7f7bd1391930> >
>>> d
<foo.Derived; proxy of <Swig Object of type 'std::shared_ptr< Derived > *' at 0x7f7bd137ce10> >
>>> d == g
False
>>> d is g
False
>>> d.foo == g.foo
True
>>> d.bar
64
>>> g.bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Base' object has no attribute 'bar'

Кажется, я не могу понять, как получить «оригинальный» прокси-объект здесь. Должен ли я создать функцию для каждого базового класса для выполнения dynamic_pointer_cast? И если да, что из подклассов Director реализовано в Python?

У меня такое ощущение, что здесь есть переключатель или функция, которую я могу включить, чтобы SWIG мог выполнить необходимый поиск в таблице и произвести нужный объект, но я еще не нашел его.

(Примечание: поведение аналогично, если я использую сырые указатели вместо общих указателей, и я не могу понять, как получить SWIG для dynamic_cast этих указателей)

Обновление

Если такого рода поведение (в частности, получение наиболее производного прокси-сервера из класса контейнера C ++, который содержит указатели на базовый класс) невозможно в SWIG, то как насчет SIP или какого-либо другого генератора оболочки для Python?

Обновление № 2

Поскольку SIP4 выглядит так, как будто он работает немного лучше, насколько разумно извлекает обернутый объект, я еще раз изменю вопрос. Проверьте мой собственный ответ ниже для деталей относительно моих текущих проблем. Я все еще приму хороший ответ на оригинальный вопрос SWIG, так как я предпочитаю его в целом, но мои новые вопросы, в основном:

  • Как я могу разумно иметь дело с обертками вокруг shared_ptr s, а не с необработанными указателями? Если это поможет, все мои классы подкласс enable_shared_from_this из их базовых базовых классов и выставить соответствующую функцию для получения общего указателя.

  • Как я могу, используя любую из систем сборки SIP4 (генератор Makefile или расширение distutils), создать мой небольшой пример проекта без необходимости сначала создавать и устанавливать общую библиотеку или редактировать созданный Makefile вручную?

1 Ответ

0 голосов
/ 14 июля 2010

Чтобы (частично) ответить на мой собственный вопрос, SIP, кажется, делает правильные вещи, как для класса «Производные» C ++, так и для подкласса уровня Python - по крайней мере, когда я использую сырые указатели.

Похоже, мне нужно выяснить, как заставить его работать с shared_ptr s (выглядит не так просто, как %include <std_shared_ptr.i> в SWIG).

Кроме того, обаОпции SIP "build system" (генератор Makefile и расширение distutils) кажутся немного странными.Ни один из примеров в их руководстве не «работает» - похоже, они ожидают, что будет очевидно, что вы должны скомпилировать и установить разделяемую библиотеку и файл заголовка в вашей библиотеке / включить пути для маленькой библиотеки Hello World, которую вы пытаетесьобернуть.Возможно, я пропустил опцию «Я просто хочу собрать и запустить эту самодостаточную вещь прямо здесь», но даже python setup.py build_ext --inplace терпит неудачу, потому что не может найти упакованный заголовок, который я поместил в текущийя знаю, каталог , который, по-видимому, является запутанным местом для этого.

...