SWIG,提升共享指针和继承

Ben*_*war 7 c++ python swig boost shared-ptr

我遇到了SWIG,共享指针和继承问题.

我正在创建各种继承的c ++类,使用Boost共享指针来引用它们,然后用SWIG包装这些共享指针来创建python类.

我的问题如下:

  • B是A的子类
  • sA是指向A的共享指针
  • sB是指向B的共享指针
  • f(sA)是期望到A的共享指针的函数

  • 如果我将sB传递给f(),则会引发错误.

  • 此错误仅发生在python级别.
  • 在C++级别,我可以毫无问题地将sB传递给f().

我有提升1.40和swig 1.3.40.

以下是5个文件的内容,它们将重现以下问题:

python setup.py build_ext --inplace
python test.py
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

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 ()); };
Run Code Online (Sandbox Code Playgroud)

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>;
Run Code Online (Sandbox Code Playgroud)

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"],
       )
Run Code Online (Sandbox Code Playgroud)

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) 
Run Code Online (Sandbox Code Playgroud)

Set*_*son 5

SWIG 对这个boost::shared_ptr<T>类一无所知。因此,它不能说derived_sptr可以“强制转换”(我相信,这是用一些疯狂的构造函数和模板元编程实现的)到derived_sptr. 因为 SWIG 需要相当简单的类定义(或包含带有 的简单文件%include),您将无法准确地声明shared_ptr该类,因为 Boost的编译器补偿和模板技巧非常不简单。

至于解决方案:是否绝对有必要分发共享指针?SWIG 的 C++ 包装器基本上用作共享指针。Boost 和 SWIG 很难合作。


Ben*_*war 5

进行以下更改可以解决该问题。

swig_shared_ptr.i中,两行:

%template(base_sptr) boost::shared_ptr<Base>;
%template(derived_sptr) boost::shared_ptr<Derived>;
Run Code Online (Sandbox Code Playgroud)

被移动,以便它们位于线上方

%include <swig_shared_ptr.h>
Run Code Online (Sandbox Code Playgroud)

然后用(在SWIG 1.3中)替换为:

SWIG_SHARED_PTR(Base, Base)
SWIG_SHARED_PTR_DERIVED(Derived, Base, Derived)    
Run Code Online (Sandbox Code Playgroud)

或(在SWIG 2.0中)通过:

%shared_ptr(Base)
%shared_ptr(Derived)
Run Code Online (Sandbox Code Playgroud)