首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Python 中使用 SIP4 和 C++0x 实现共享指针

Python 中使用 SIP4 和 C++0x 实现共享指针

原创
作者头像
用户11021319
发布2024-04-11 10:04:37
发布2024-04-11 10:04:37
20900
代码可运行
举报
运行总次数:0
代码可运行

1. 问题背景

在 Python、C++0x 和 SWIG 2.0 中,构建如下 C++ 代码时遇到问题:

代码语言:python
代码运行次数:0
运行
复制
#include <string>
#include <iostream>
#include <memory>
using namespace std;

struct Base {
  virtual string name();
  int foo;
  shared_ptr<Base> mine;
  Base(int);
  virtual ~Base() {}
  virtual void doit(shared_ptr<Base> b) {
    cout << name() << " doing it to " << b->name() << endl;
    mine = b;
  }
  virtual shared_ptr<Base> getit() {
    return mine;
  }
};

struct Derived : Base {
  virtual string name();
  int bar;
  Derived(int, int);
};

对应的接口文件如下:

代码语言:python
代码运行次数:0
运行
复制
%module(directors="1") foo
%feature("director");

%include <std_string.i>

%include <std_shared_ptr.i>
%shared_ptr(Base)
%shared_ptr(Derived)

%{
#define SWIG_FILE_WITH_INIT
#include "foo.hpp"
%}

%include "foo.hpp"

在 Python 会话中,执行如下操作:

代码语言:python
代码运行次数:0
运行
复制
>>> import foo
>>> b = foo.Base(42)
>>> d = foo.Derived(23,64)
>>> b.doit(d)
Base doing it to Derived
>>> g = b.getit()
>>> g
<foo.Base; proxy of <Swig Object of type 'std::shared_ptr< Base > *' at 0x7f7bd1391930> >
>>> d
<foo.Derived; proxy of <Swig Object of type 'std::shared_ptr< Derived > *' at 0x7f7bd137ce10> >
>>> d == g
False
>>> d is g
False
>>> d.foo == g.foo
True
>>> d.bar
64
>>> g.bar
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Base' object has no attribute 'bar'

问题在于,无法从 C++ 容器类中获取最派生的代理对象。不知道是否需要为每个基类生成一个函数来执行动态指针转换,如果是,那么用 Python 实现的 Director 子类又该如何处理?

2. 解决方案

2.1 使用 SIP4 解决问题

SWIG 似乎无法解决此问题,但 SIP4 可以。SIP4 提供了更好的方式来处理共享指针的包装器。

可以使用 SIP4 的 Makefile 生成器或 distutils 扩展构建系统来构建示例项目,而无需首先生成和安装共享库或手动编辑生成的 Makefile。

2.2 代码示例

以下是使用 SIP4 构建示例项目的具体步骤:

1. 安装 SIP4

代码语言:python
代码运行次数:0
运行
复制
pip install sip

2. 创建 SIP 模块文件

代码语言:python
代码运行次数:0
运行
复制
[sip]
includedir = /usr/include/python3.9
sipdir = /usr/share/sip/sip
bindingdir = /usr/share/sip/bindings
moduledir = /usr/share/sip/modules
debug = True

3. 创建 C++ 头文件

代码语言:python
代码运行次数:0
运行
复制
#include <string>
#include <iostream>
#include <memory>
using namespace std;

class Base {
public:
  virtual string name() { return "Base"; }
  virtual void print() { cout << "Base" << endl; }
};

class Derived : public Base {
public:
  virtual string name() { return "Derived"; }
  virtual void print() { cout << "Derived" << endl; }
};

4. 创建 SIP 接口文件

代码语言:javascript
代码运行次数:0
运行
复制
class Base {
    string name();
    void print();
};

class Derived : Base {
    string name();
    void print();
};

5. 运行 SIP 生成绑定代码

代码语言:python
代码运行次数:0
运行
复制
sip -c sip.cfg -b build -t Qt5 Base.h

6. 编译并安装绑定代码

代码语言:javascript
代码运行次数:0
运行
复制
cd build
make
sudo make install

7. 在 Python 中导入绑定代码

代码语言:javascript
代码运行次数:0
运行
复制
from Base import Base, Derived

b = Base()
d = Derived()

b.print()  # 输出 "Base"
d.print()  # 输出 "Derived"

通过以上步骤,可以在 Python 中使用 SIP4 来处理共享指针的包装器,并构建示例项目。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 问题背景
  • 2. 解决方案
    • 2.1 使用 SIP4 解决问题
    • 2.2 代码示例
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档