You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用SWIG为Python包装带std::shared_ptr输出引用的C++ void函数

用SWIG包装C++输出型std::shared_ptr为Python返回值

要实现Python中通过p = makeWidget()获取Widget的智能指针,核心是用SWIG typemap处理C++函数的引用型输出参数,同时正确管理shared_ptr的生命周期,避免段错误。以下是完整的解决方案:

1. 编写SWIG接口文件(widget.i)

%module widget

// 引入SWIG对std::shared_ptr的支持
%include <std_shared_ptr.i>
%shared_ptr(Widget)

// 输入typemap:创建空shared_ptr作为引用参数的载体,标记无需Python传参
%typemap(in, numinputs=0) std::shared_ptr<Widget>& OUTPUT (std::shared_ptr<Widget> temp) {
    $1 = &temp;
}

// 输出typemap:将函数修改后的shared_ptr转为Python对象返回
%typemap(argout) std::shared_ptr<Widget>& OUTPUT {
    PyObject* obj = SWIG_NewPointerObj(
        SWIG_as_voidptr($1->get()), 
        $descriptor(Widget*), 
        SWIG_POINTER_OWN
    );
    $result = obj;
}

// 声明C++结构体与函数
struct Widget {
    int value;
};

void makeWidget(std::shared_ptr<Widget>& OUTPUT);

关键typemap解释

  • numinputs=0:告诉SWIG这个参数不需要Python传入,实现无参调用makeWidget()
  • 临时变量temp:创建一个空的std::shared_ptr<Widget>,确保函数有有效的引用可以修改,避免野指针导致的段错误
  • SWIG_POINTER_OWN:标记Python拥有该对象的所有权,SWIG会自动协调Python引用计数与C++ shared_ptr的生命周期

2. C++实现代码(widget.cpp)

#include "widget.h"

void makeWidget(std::shared_ptr<Widget>& out_ptr) {
    out_ptr = std::make_shared<Widget>();
    out_ptr->value = 42; // 示例初始化值
}

对应的头文件(widget.h):

#include <memory>

struct Widget {
    int value;
};

void makeWidget(std::shared_ptr<Widget>& out_ptr);

3. 编译与测试

编译命令

# 生成SWIG包装代码
swig -python -c++ widget.i

# 编译C++代码与包装代码
g++ -fPIC -c widget.cpp widget_wrap.cxx -I/usr/include/python3.10 # 替换为你的Python头文件路径

# 生成共享库
g++ -shared widget.o widget_wrap.o -o _widget.so

Python测试

import widget

# 无参调用获取Widget实例
p = widget.makeWidget()
print(p.value) # 输出:42

这个方案无需手动修改SWIG生成的包装代码,就能正确实现Python无参调用并返回智能指针包装的Widget对象,彻底解决之前的段错误问题。

内容的提问来源于stack exchange,提问作者Lars Ericson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 13:25:56