具有模板化类的 SWIG_SHARED_PTR 宏

发布于 2024-10-30 18:33:56 字数 15374 浏览 2 评论 0 原文

我使用 SWIG 和 boost 共享指针来创建 python 扩展。我当前的问题是 SWIG_SHARED_PTR 宏似乎与模板类的工作方式不同。我将给出两个示例,一个没有模板(示例),一个有模板(示例2)。

首先,我将包含代码,最后展示 python 中两个扩展的行为差异。

基本问题是,如果没有模板,共享指针在 python 中显示为

>

而当包装类是实例化模板时,显示为

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

example.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                                                                                                         

使用模板(不不起作用)

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

example2.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

I'm using SWIG with boost shared pointers to create python extensions. My current issue is that the SWIG_SHARED_PTR macro seems to work differently with templated classes. I'll give two examples, one without templates (example), and one with templates (example2).

First I'll include the code, and at the end show the difference in behavior of the two extensions within python.

The basic problem is that without templates the shared pointers appear in python as

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

whereas when the wrapped class is an instantiated template the appear as

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

I'm new to C++ templates so it's quite possible the problems I'm having have nothing to do with SWIG.

Without Templates (works fine)

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

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

example2.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>;                                                                                       

Example of Difference:

> 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

梦冥 2024-11-06 18:33:57

SWIG 对于对象暴露给它的顺序及其内部类型系统非常敏感。

尝试移动您的 %template 语句,使其位于 SWIG_SHARED_PTR 语句之前。

SWIG can be very touchy about the order in which objects are exposed to it, with its internal type system.

Try moving your %template statements so that they come before your SWIG_SHARED_PTR statements.

無心 2024-11-06 18:33:57

在 example2.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>)

In example2.i the lines

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

should be replaced by

SWIG_SHARED_PTR(base_int_sptr, Base<int>)                              
SWIG_SHARED_PTR_DERIVED(derived_int_sptr, Base<int>, Derived<int>)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文