SWIG c++ / python:如何处理 std::map of shared_ptr of abstract class
SWIG c++ / python: how to handle a std::map of shared_ptr of abstract class
如何使用来自以下 C++ 代码的 SWIG 处理 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 可以是导演 class。
我的问题:
- 与此问题相关的最小 .i 文件是什么?
- 我还读到这会导致 python/C++ 棘手的所有权
例如 my_B 被删除时的问题。我怎样才能轻松转移
"my_B" 所有权从 python 到 C++ ?
非常感谢您的帮助
一个。
这是一个跟踪 construction/destruction 的工作示例,以显示共享指针的引用计数正在工作:
test.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()
如何使用来自以下 C++ 代码的 SWIG 处理 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 可以是导演 class。
我的问题:
- 与此问题相关的最小 .i 文件是什么?
- 我还读到这会导致 python/C++ 棘手的所有权 例如 my_B 被删除时的问题。我怎样才能轻松转移 "my_B" 所有权从 python 到 C++ ?
非常感谢您的帮助
一个。
这是一个跟踪 construction/destruction 的工作示例,以显示共享指针的引用计数正在工作:
test.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()