SWIG, повысить общие указатели и наследование - PullRequest
7 голосов
/ 17 января 2011

У меня проблемы с SWIG, общими указателями и наследованием.

Я создаю различные классы c ++, которые наследуются друг от друга, использую общие указатели Boost для обращения к ним, а затем заключаю в них эти общие указателис SWIG для создания классов Python.

Моя проблема заключается в следующем:

  • B является подклассом A
  • sA является общим указателем на A
  • sB - это общий указатель на B
  • f (sA) - функция, ожидающая общего указателя на A

  • Если я передам sB вf (), тогда возникает ошибка.

  • Эта ошибка возникает только на уровне python.
  • На уровне C ++ я могу без проблем передать sB в f ().

У меня Boost 1.40 и Swig 1.3.40.

Ниже приведено содержимое 5 файлов, которые будут воспроизводить проблему с:

python setup.py build_ext --inplace
python test.py

swig_shared_ptr.h

#ifndef INCLUDED_SWIG_SHARED_PTR_H
#define INCLUDED_SWIG_SHARED_PTR_H

#include <boost/shared_ptr.hpp>

class Base {};

class Derived : public Base {};

typedef boost::shared_ptr<Base> base_sptr;
typedef boost::shared_ptr<Derived> derived_sptr;

void do_something (base_sptr bs);

base_sptr make_base();
derived_sptr make_derived();

#endif

swig_shared_ptr.cc

#include <iostream>
#include "swig_shared_ptr.h"

void do_something (base_sptr bs)
{
  std::cout << "Doing something." << std::endl;
}

base_sptr make_base() { return base_sptr(new Base ()); };
derived_sptr make_derived() { return derived_sptr(new Derived ()); };

swig_shared_ptr.i

%module(docstring="
Example module showing problems I am having with SWIG, shared pointers
and inheritance.
") swig_shared_ptr

%{
#include "swig_shared_ptr.h"
%}

%include <swig_shared_ptr.h>
%include <boost_shared_ptr.i>
%template(base_sptr) boost::shared_ptr<Base>;
%template(derived_sptr) boost::shared_ptr<Derived>;

setup.py

"""
setup.py file for swig_shared_ptr
"""

from distutils.core import setup, Extension

swig_shared_ptr_module = Extension('_swig_shared_ptr',
                         include_dirs = ['/usr/include/boost'],
                         sources=['swig_shared_ptr.i', 'swig_shared_ptr.cc'],
                         )

setup (name = 'swig_shared_ptr',
       version = '0.1',
       author = "Ben",
       description = """Example showing problems I am having with SWIG, shared
                        pointers and inheritance.""",
       ext_modules = [swig_shared_ptr_module],
       py_modules = ["swig_shared_ptr"],
       )

test.py

import swig_shared_ptr as ssp

bs = ssp.make_base()
dr = ssp.make_derived()

# Works fine.
ssp.do_something(bs) 
# Fails with "TypeError: in method 'do_something', argument 1 of type 'base_sptr'"
ssp.do_something(dr) 

Ответы [ 2 ]

4 голосов
/ 12 марта 2011

Следующее изменение решает проблему.

В swig_shared_ptr.i две строки:

%template(base_sptr) boost::shared_ptr<Base>;
%template(derived_sptr) boost::shared_ptr<Derived>;

перемещены так, что они находятся над линией

%include <swig_shared_ptr.h>

и затем заменяются (в SWIG 1.3) на:

SWIG_SHARED_PTR(Base, Base)
SWIG_SHARED_PTR_DERIVED(Derived, Base, Derived)    

или (в SWIG 2.0) на:

%shared_ptr(Base)
%shared_ptr(Derived)
3 голосов
/ 17 января 2011

SWIG ничего не знает о классе boost::shared_ptr<T>. Следовательно, он не может сказать, что derived_sptr может быть "приведен" (что, я считаю, реализовано с помощью сумасшедших конструкторов и шаблонного метапрограммирования) в derived_sptr. Поскольку SWIG требует довольно простых определений классов (или включения простых файлов с %include), вы не сможете точно объявить класс shared_ptr, потому что Boost невероятно непрост с его компилятором Компенсация и шаблонные хитрости.

Что касается решения: необходимо ли раздавать общие указатели? Оболочки SWIG C ++ в основном функционируют как общие указатели. Boost и SWIG очень и очень трудно заставить работать вместе.

...