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)
I'm having trouble with SWIG, shared pointers, and inheritance.
I am creating various c++ classes which inherit from one another, using
Boost shared pointers to refer to them, and then wrapping these shared
pointers with SWIG to create the python classes.
My problem is the following:
- B is a subclass of A
- sA is a shared pointer to A
- sB is a shared pointer to B
f(sA) is a function expecting a shared pointer to A
If I pass sB to f() then an error is raised.
- This error only occurs at the python level.
- At the C++ level I can pass sB to f() without a problem.
I have boost 1.40 and swig 1.3.40.
Below are the contents of 5 files which will reproduce the problem
with:
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)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
以下更改似乎可以解决该问题。
在 swig_shared_ptr.i 中,两行:
被移动,以便它们位于该行上方
,然后(在 SWIG 1.3 中)替换为:
或(在 SWIG 2.0 中)替换为:
The following change appears to solve the problem.
In swig_shared_ptr.i the two lines:
are moved so that they are above the line
and are then replaced (in SWIG 1.3) by:
or (in SWIG 2.0) by:
SWIG 对
boost::shared_ptr
类一无所知。因此,它无法判断衍生_sptr
可以“转换”(我相信,这是通过一些疯狂的构造函数和模板元编程实现的)到衍生_sptr
。由于 SWIG 需要相当简单的类定义(或使用%include
包含简单文件),因此您将无法准确声明shared_ptr
类,因为 Boost 是 难以置信其编译器补偿和模板技巧并不简单。至于解决方案:是否绝对有必要分发共享指针? SWIG 的 C++ 包装器基本上充当共享指针。 Boost 和 SWIG 很难协同工作。
SWIG doesn't know anything about the
boost::shared_ptr<T>
class. It therefore can't tell thatderived_sptr
can be "cast" (which is, I believe, implemented with some crazy constructors and template metaprogramming) toderived_sptr
. Because SWIG requires fairly simple class definitions (or inclusion of simple files with%include
), you won't be able to accurately declare theshared_ptr
class, because Boost is incredibly non-simple with its compiler compensation and template tricks.As to a solution: is it absolutely necessary to hand out shared pointers? SWIG's C++ wrappers basically function as shared pointers. Boost and SWIG are very, very difficult to get to work together.