2011-01-17 8 views
7

Tengo problemas con SWIG, punteros compartidos y herencia.SWIG, impulsar punteros compartidos y herencia

estoy creando diversas clases de C++ que heredan el uno del otro, utilizando punteros compartidos Boost para referirse a ellos, y luego envolver estos punteros compartidos con TRAGO para crear las clases de Python.

Mi problema es el siguiente:

  • B es una subclase de A
  • SA es un puntero compartido a un
  • SB es un puntero compartida a B
  • f (SA) es una función que espera un puntero compartido a A

  • Si paso sB a f(), se produce un error.

  • Este error solo ocurre en el nivel python.
  • En el nivel C++ puedo pasar sB a f() sin ningún problema.

Tengo boost 1.40 y swig 1.3.40.

A continuación se presentan los contenidos de 5 archivos que reproducir el problema con :

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) 

Respuesta

4

El siguiente cambio parece resolver el problema.

En swig_shared_ptr.i las dos líneas:

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

se mueven de manera que están por encima de la línea de

%include <swig_shared_ptr.h> 

y entonces se reemplazan (en SWIG 1,3) por:

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

o (en SWIG 2.0) por:

%shared_ptr(Base) 
%shared_ptr(Derived) 
3

TRAGO no sabe nada acerca de la clase boost::shared_ptr<T>. Por lo tanto, no se puede decir que derived_sptr se puede "convertir" (que es, creo, implementado con algunos desarrolladores locos y metaprogramación de plantillas) al derived_sptr. Debido a que SWIG requiere definiciones de clase bastante simples (o inclusión de archivos simples con %include), no podrá declarar con precisión la clase shared_ptr, porque Boost es increíblemente no simple con su compilación de compensación y trucos de plantilla.

En cuanto a una solución: ¿es absolutamente necesario repartir punteros compartidos? Los contenedores de C++ de SWIG básicamente funcionan como punteros compartidos. Boost y SWIG son muy, muy difíciles de trabajar juntos.

+0

Gracias por responder. Ahora sé por qué estoy teniendo tantos problemas. –

+1

@gyroidben: si esto responde su pregunta, haga clic en la marca de verificación junto a mi respuesta. Además, si el uso de Python con boost es tan importante, es posible que desee echarle un vistazo a Boost :: Python también. –

+0

@gyroidben hay alternativas a SWIG con respecto a Python. Boost :: Python combinado con Py ++ crea el mismo tipo de integración de lenguaje cruzado automático pero puede manejar tipos de Boost. – wheaties

Cuestiones relacionadas