Python 中的 Swig 控制器和智能指针

bur*_*bum 6 swig python-3.x c++11

在使用 Swig 尝试将智能指针包装到 Python 中的导演类时,我遇到了一些问题。我知道文档说支持有限,但我想知道 Swig 是否支持我的场景。

简而言之,如果一个导演类在 Python 中扩展并作为智能指针传递,当 Python 对象死亡时,内存区域也会消失。如果__disown__用于防止这种情况发生,则会发生内存泄漏(另请参见http://swig.10945.n7.nabble.com/Using-director-shared-pointer-disown-gt-memory-leak-td11821.html)。

这是一个显示问题的最小示例。

示例.h:

#ifndef EXAMPLE_H
#define EXAMPLE_H

#include <string>
#include <memory>

namespace example
{

class ContentBase
{
public:
    ContentBase() {}

    virtual ~ContentBase() {}

    virtual std::string get_name() { return "ContentBase " + m_name; }

    virtual void set_name(const std::string& name) { m_name = name; }

private:
    std::string m_name;
};

class Container
{
public:
    Container() {}

    void set_content(std::shared_ptr<ContentBase> content) { m_content = content; }

    std::shared_ptr<ContentBase> get_content() { return m_content; }

private:
    std::shared_ptr<ContentBase> m_content;
};

} // namespace example

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

示例.i:

%module(directors="1") example

%include "std_string.i"
%include <std_shared_ptr.i>

%{
#include "example.h"
%}

%shared_ptr(example::ContentBase)
%feature("director") example::ContentBase;

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

test_example.py:

import pytest

import example as e

class PyContent(e.ContentBase):
    def __init__(self, *args, **kwargs):
        e.ContentBase.__init__(self, *args, **kwargs)
        self.name = "empty"
        #self.__disown__()

    def get_name(self):
        return "py " + self.name

    def set_name(self, n):
        self.name = n

def set_python_content(container):
    content = PyContent()
    content.set_name("content")
    container.set_content(content)

    content2 = container.get_content()
    assert content2.get_name() == "py content"

def test_python_inheritance():
    container = e.Container()
    set_python_content(container)

    content = container.get_content()
    assert content.get_name() == "py content"
Run Code Online (Sandbox Code Playgroud)

ContentBase只要至少有一个 Python 引用或一个共享指针处于活动状态(并且没有内存泄漏),有没有办法保持活动状态?

注意:我使用的是 Swig 3.0.12,但即使使用从 Github 编译的最新版本 (c44adff7b9f5dc675d7c2dbbf4ea36660c3b1466) 也会出现相同的行为。