SWIG、Boost共享指针与继承
我在使用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 个回答
5
SWIG对boost::shared_ptr<T>
这个类并不了解。所以它无法判断derived_sptr
是否可以“转换”(我觉得这是通过一些复杂的构造函数和模板元编程实现的)为derived_sptr
。因为SWIG需要比较简单的类定义(或者通过%include
引入简单的文件),所以你无法准确地声明shared_ptr
类,因为Boost的实现非常复杂,涉及到编译器的补偿和模板的各种技巧。
至于解决办法:真的有必要使用共享指针吗?SWIG的C++包装器基本上就像共享指针一样。Boost和SWIG的配合非常非常困难。
6
以下的修改似乎解决了这个问题。
在 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)