Макрос SWIG_SHARED_PTR с шаблонным классом

#c #python #templates #swig #shared-ptr

#c #python #шаблоны #swig #общий доступ-ptr

Вопрос:

Я использую SWIG с общими указателями boost для создания расширений python. Моя текущая проблема заключается в том, что макрос SWIG_SHARED_PTR, похоже, работает по-другому с шаблонными классами. Я приведу два примера, один без шаблонов (example) и один с шаблонами (example2).

Сначала я включу код, а в конце покажу разницу в поведении двух расширений в python.

Основная проблема заключается в том, что без шаблонов общие указатели отображаются в python как

<example.Derived; proxy of <Swig Object of type 'derived_sptr *' at 0xb772c4b8> >

принимая во внимание, что когда обернутый класс является созданным шаблоном, он отображается как

<Swig Object of type 'derived_int_sptr *' at 0xb787e4b8>

Я новичок в шаблонах C , поэтому вполне возможно, что проблемы, с которыми я сталкиваюсь, не имеют ничего общего с SWIG.

Без шаблонов (работает нормально)

example.h

 #include <boost/shared_ptr.hpp>                                                                                                

#ifndef EXAMPLE_H                                                                                                              
#define EXAMPLE_H                                                                                                              

class Base {                                                                                                                   
 public:                                                                                                                       
  Base(int number1);                                                                                                           
  int get_number1();                                                                                                           
  virtual int get_number2() = 0;                                                                                               
 protected:                                                                                                                    
  int number1;                                                                                                                 
};                                                                                                                             

class Derived : public Base {                                                                                                  
 public:                                                                                                                       
  Derived(int number1, int number2);                                                                                           
  int get_number2();                                                                                                           
 private:                                                                                                                      
  int number2;                                                                                                                 
};                                                                                                                             

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

derived_sptr make_derived(int number1, int number2);                                                                           

int get_number1(base_sptr b);                                                                                                  

#endif
  

example.cc

 #include "example.h"                                                                                                       

Base::Base(int number1) :                                                                                                  
  number1(number1)                                                                                                         
{}                                                                                                                         

int Base::get_number1() {                                                                                                  
  return number1;                                                                                                          
}                                                                                                                          

Derived::Derived(int number1, int number2) :                                                                               
  Base(number1),                                                                                                           
  number2(number2)                                                                                                         
{}                                                                                                                         

int Derived::get_number2() {                                                                                               
  return number2;                                                                                                          
}                                                                                                                          

derived_sptr make_derived(int number1, int number2) {                                                                      
  return derived_sptr(new Derived(number1, number2));                                                                      
}                                                                                                                          

int get_number1(base_sptr b) {                                                                                             
  return b->get_number1();                                                                                                 
}
  

пример.i

 %module example                                                                                                            
%{                                                                                                                         
  #include "example.h"                                                                                                     
%}                                                                                                                         

%include boost_shared_ptr.i                                                                                                

SWIG_SHARED_PTR(base_sptr, Base)                                                                                           
SWIG_SHARED_PTR_DERIVED(derived_sptr, Base, Derived)                                                                       

%include example.h                                                                                                         
  

With Templates (doesn’t work)

example2.h

 #include <boost/shared_ptr.hpp>                                                                                            

#ifndef EXAMPLE2_H                                                                                                          
#define EXAMPLE2_H                                                                                                          

template <typename T>                                                                                                      
class Base {                                                                                                               
 public:                                                                                                                   
  Base(T number1);                                                                                                         
  T get_number1();                                                                                                         
  virtual T get_number2() = 0;                                                                                             
 protected:                                                                                                                
  T number1;                                                                                                               
};                                                                                                                         

template <typename T>                                                                                                      
class Derived : public Base<T> {                                                                                           
 public:                                                                                                                   
  Derived(T number1, T number2);                                                                                           
  T get_number2();                                                                                                         
 private:                                                                                                                  
  T number2;                                                                                                               
};                                                                                                                         

typedef Base<int> base_int;                                                                                                
typedef Derived<int> derived_int;                                                                                          

typedef boost::shared_ptr<base_int> base_int_sptr;                                                                         
typedef boost::shared_ptr<derived_int> derived_int_sptr;                                                                   

derived_int_sptr make_derived_int(int number1, int number2);                                                               

int get_number1_int(base_int_sptr b);          

#endif
  

example2.cc

 #include "example2.h"                                                                                                       

template <typename T>                                                                                                      
Base<T>::Base(T number1) :                                                                                                 
  number1(number1)                                                                                                         
{}                                                                                                                         

template <typename T>                                                                                                      
T Base<T>::get_number1() {                                                                                                 
  return number1;                                                                                                          
}                                                                                                                          

template <typename T>                                                                                                      
Derived<T>::Derived(T number1, T number2) :                                                                                
  Base<T>(number1),                                                                                                        
  number2(number2)                                                                                                         
{}                                                                                                                         

template <typename T>                                                                                                      
T Derived<T>::get_number2() {                                                                                              
  return number2;                                                                                                          
}                                                                                                                          

template class Base<int>;                                                                                                  
template class Derived<int>;                                                                                               

derived_int_sptr make_derived_int(int number1, int number2) {                                                              
  return derived_int_sptr(new Derived<int>(number1, number2));                                                             
}                                                                                                                          

int get_number1_int(base_int_sptr b) {                                                                                     
  return b->get_number1();                                                                                                 
} 
  

пример2.i

 %module example2                                                                                                            
%{                                                                                                                         
  #include "example2.h"                                                                                                     
%}                                                                                                                         

%include boost_shared_ptr.i                                                                                                

SWIG_SHARED_PTR(base_int_sptr, base_int)                                                                                   
SWIG_SHARED_PTR_DERIVED(derived_int_sptr, base_int, derived_int)                                                           

%include example.h                                                                                                         

%template(base_int) Base<int>;                                                                                             
%template(derived_int) Derived<int>;                                                                                       
  

Пример различия:

 > import example
> d = example.make_derived(4, 5)
> d
> <example.Derived; proxy of <Swig Object of type 'derived_sptr *' at 0xb77327a0> >
> d.get_number1()
4
> example.get_number1(d)
4
> import example2
> d = example2.make_derived_int(4, 5)
> d
<Swig Object of type 'derived_int_sptr *' at 0xb787e4b8>
> d.get_number1()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'SwigPyObject' object has no attribute 'get_number1'
> example.get_number1_int(d)
4
  

Ответ №1:

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

Попробуйте переместить свои %template инструкции так, чтобы они шли перед вашими SWIG_SHARED_PTR инструкциями.

Комментарии:

1. Если я это сделаю, я получу сообщения об ошибках: example.i:7: Ошибка: Шаблон ‘Base’ не определен. пример.i: 8: Ошибка: «Производный» шаблон не определен. пример.i:11: Предупреждение (303): %extend определено для необъявленного класса derived_int. Я понимаю, что операторы %template должны появляться после определения шаблона, но макрос SWIG_SHARED_PTR должен появляться заранее. Я продолжу играть с упорядочением, чтобы посмотреть, смогу ли я заставить что-то работать. Спасибо за предложение.

2. Я нашел проблему. Спасибо за предложение, оно указало мне правильное направление.

Ответ №2:

В примере 2.i строки

 SWIG_SHARED_PTR(base_int_sptr, base_int) 
SWIG_SHARED_PTR_DERIVED(derived_int_sptr, base_int, derived_int)
  

должен быть заменен на

 SWIG_SHARED_PTR(base_int_sptr, Base<int>)                              
SWIG_SHARED_PTR_DERIVED(derived_int_sptr, Base<int>, Derived<int>)