【问题标题】:SWIG c++ / python: how to handle a std::map of shared_ptr of abstract classSWIG c++ / python:如何处理抽象类的 shared_ptr 的 std::map
【发布时间】:2020-08-12 12:52:05
【问题描述】:

如何使用 SWIG 从以下 c++ 代码处理 python 中的抽象方法映射:

class A : Base {
    virtual int f() = 0;
};

class B : public A {
    int f() { return 10 }; 
}; 

class C : public A {
    int f() { return 20 }; 
}; 

std::map< std::string, std::shared_ptr<A>> my_map; 

在python中,我也想做类似的事情:

my_B = B()
my_map["foo"] = my_B

或者可能更简单:

my_map["foo"] = B()

为了使用跨语言多态性,我必须明确 A 或 B 可以是主管类。

我的问题:

  1. 与此问题相关的最小 .i 文件可能是什么?
  2. 我还读到这会导致 python/C++ 棘手的所有权 例如,如果 my_B 被删除,则会出现问题。我怎样才能轻松转移 从 python 到 C++ 的“my_B”所有权?

非常感谢您的帮助

A.

【问题讨论】:

    标签: python c++ abstract-class swig stdmap


    【解决方案1】:

    这是一个跟踪构造/销毁以显示共享指针的引用计数正在工作的工作示例:

    测试.h

    #include <map>
    #include <memory>
    #include <string>
    #include <iostream>
    
    class A {
    public:
        virtual int f() = 0;
        A() { std::cout << "A()" << std::endl; }
        virtual ~A() { std::cout << "~A()" << std::endl; }
    };
    
    class B : public A {
    public:
        int f() { return 10; }
        B() { std::cout << "B()" << std::endl; }
        virtual ~B() { std::cout << "~B()" << std::endl; }
    };
    
    class C : public A {
    public:
        int f() { return 20; }
        C() { std::cout << "C()" << std::endl; }
        virtual ~C() { std::cout << "~C()" << std::endl; }
    };
    
    std::map< std::string, std::shared_ptr<A>> my_map;
    

    test.i

    %module test
    
    %{
    #include "test.h"
    %}
    
    %include <std_map.i>
    %include <std_shared_ptr.i>
    %include <std_string.i>
    
    // declare all visible shared pointers so SWIG generates appropriate wrappers
    // before including the header.
    %shared_ptr(A)
    %shared_ptr(B)
    %shared_ptr(C)
    
    %include "test.h"
    
    // Declare the template instance used so SWIG will generate the wrapper.
    %template(Map) std::map<std::string, std::shared_ptr<A>>;
    

    输出:

    >>> import test
    >>>
    >>> m=test.cvar.my_map    # global variables are in module's cvar.
    >>> m['foo'] = test.C()
    A()
    C()
    >>> m['foo'].f()
    20
    >>> del m['foo']  # only reference, so it is freed
    ~C()
    ~A()
    >>> b = test.B()  # 1st reference
    A()
    B()
    >>> m['bar'] = b  # 2nd reference
    >>> del m['bar']  # NOT freed.
    >>> del b         # now it is freed.
    ~B()
    ~A()
    

    【讨论】:

    • 非常感谢您的帮助,__disown__() 函数似乎也可以正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-29
    • 2014-10-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多