在Python中实例化来自SWIG的shared_ptr对象

Nic*_*mer 2 c++ python swig

我有BaseClass一些派生类

#ifndef TEST_H__
#define TEST_H__

#include <iostream>
#include <memory>

class BaseClass
{
  public:
  virtual double eval(double x) const = 0;
};

class Square: public BaseClass
{
  public:
  double eval(double x) const {return x*x;}
};

class Add1: public BaseClass
{
  public:
  Add1(BaseClass & obj): obj_(obj) {}

  double eval(double x) const {return obj_.eval(x) + 1.0;}

  private:
  BaseClass & obj_;
};

#endif /* TEST_H__ */
Run Code Online (Sandbox Code Playgroud)

用SWIGàla治疗

%module test

%{
#define SWIG_FILE_WITH_INIT
%}

%{
#include "test.h"
%}

%include "test.h"
Run Code Online (Sandbox Code Playgroud)

这可以从Python中使用

import test
s = test.Square()
a = test.Add1(s)
print(a.eval(2.0))
Run Code Online (Sandbox Code Playgroud)

什么是segfaulting:

import test
a = test.Add1(test.Square())
print(a.eval(2.0))
Run Code Online (Sandbox Code Playgroud)

为什么?在test.Square()没有分配给一个变量,因此不分配给后存在了a,并obj_指向无效的存储.

为了避免这种行为,使用的想法std::shared_ptr<BaseClass>代替BaseClass&,即

class Add1: public BaseClass
{
  public:
  Add1(std::shared_ptr<BaseClass> & obj): obj_(obj) {}

  double eval(double x) const {return obj_->eval(x) + 1.0;}

  private:
  std::shared_ptr<BaseClass> obj_;
};
Run Code Online (Sandbox Code Playgroud)

这个确切的代码虽然不起作用

TypeError: in method 'new_Add1', argument 1 of type 'std::shared_ptr< BaseClass > &'
Run Code Online (Sandbox Code Playgroud)

有道理,太:test.Square()不返回std::shared_ptr<BaseClass>,但只是一个Square又名BaseClass实例.

是否可以test.Square()返回共享指针std::shared_ptr<Square>

Fle*_*exo 6

SWIG对此有很好的支持std::smart_ptr.这一切都非常透明,因此您需要对.i文件进行的更改只是:

%module test

%{
#define SWIG_FILE_WITH_INIT
#include "test.h"
%}

%include <std_shared_ptr.i>

%shared_ptr(Square);
%shared_ptr(BaseClass);
%shared_ptr(Add1); // Not actually needed to make your demo work, but a good idea still

%include "test.h"
Run Code Online (Sandbox Code Playgroud)

这足以使您的演示Python代码工作,我还添加了onlySquare()作为成员函数Square并调整演示来说明它:

import test
sq=test.Square()
test.Add1(sq) # implicitly converted to shared_ptr<BaseClass> here
sq.onlySquare()
print sq
# <test.Square; proxy of <Swig Object of type 'std::shared_ptr< Square > *' at 0xf7424950> >
Run Code Online (Sandbox Code Playgroud)

对于非智能指针参数它应该"正常工作",但请注意,现在所有 Python在该层次结构中创建的实例都将是"智能".

(如果你有兴趣,我也盖std::unique_ptrstd::weak_ptr前).