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

如何用SWIG将C++ int**返回值映射到Python?调用无结果排查

问题分析与修复方案

让我们一步步拆解你代码里的问题,以及如何修复:

1. 内存释放逻辑错误(内存泄漏+潜在访问风险)

你在typemap最后直接执行delete $1;,但$1是指向指针数组的指针——每个$1[i]都是用new int[4]分配的子数组。只释放外层指针数组会导致4个子数组的内存永远无法回收,造成内存泄漏;如果后续有代码意外访问已释放的内存,还会引发未定义行为。

正确的释放顺序应该是先释放每个子数组,再释放外层数组:

// 先释放所有子数组
for (int i = 0; i < 4; ++i) {
    delete[] $1[i];
}
// 再释放外层指针数组
delete[] $1;

2. Python API兼容性问题(Python3下直接失效)

PyInt_FromLong在Python3中已经被废弃并移除,取而代之的是PyLong_FromLong。如果你的环境是Python3,这一步会直接创建对象失败,导致列表元素无法正确设置,最终返回的结果可能是空列表或无效对象。

把PyInt_FromLong((long)$1[i][j])替换为PyLong_FromLong((long)$1[i][j])即可解决这个问题。

3. 缺失错误检查(静默失败的核心原因)

你的typemap代码没有任何错误检查逻辑——比如PyList_New可能因内存不足返回NULL,PyLong_FromLong也可能创建失败。一旦某个步骤出错,后续操作都会静默失败,最终返回给Python的结果就会异常(比如空列表或None)。

我们需要添加错误检查,一旦出错就清理已分配的资源并返回错误。

修复后的完整typemap代码

%typemap(out) int** {
    // 创建外层列表
    $result = PyList_New(4);
    if (!$result) {
        // 出错时先清理C++端内存
        for (int i = 0; i < 4; ++i) {
            delete[] $1[i];
        }
        delete[] $1;
        return NULL;
    }

    for(int i=0; i<4; i++) {
        // 创建内层列表
        PyObject *o = PyList_New(4);
        if (!o) {
            // 清理已创建的Python对象和C++内存
            Py_DECREF($result);
            for (int k = 0; k < i; ++k) {
                Py_DECREF(PyList_GetItem($result, k));
            }
            for (int k = 0; k < 4; ++k) {
                delete[] $1[k];
            }
            delete[] $1;
            return NULL;
        }

        for(int j=0; j<4; j++) {
            PyObject *num = PyLong_FromLong((long)$1[i][j]);
            if (!num) {
                // 清理已创建的Python对象和C++内存
                Py_DECREF(o);
                Py_DECREF($result);
                for (int k = 0; k < i; ++k) {
                    Py_DECREF(PyList_GetItem($result, k));
                }
                for (int k = 0; k < 4; ++k) {
                    delete[] $1[k];
                }
                delete[] $1;
                return NULL;
            }
            // PyList_SetItem会接管num的引用,无需手动DECREF
            PyList_SetItem(o, j, num);
        }

        // 同样,PyList_SetItem接管o的引用
        PyList_SetItem($result, i, o);
    }

    // 最后释放C++端的内存
    for (int i = 0; i < 4; ++i) {
        delete[] $1[i];
    }
    delete[] $1;
}

额外验证点

  • 确保你的.i文件中,typemap定义在myfunction函数声明之前(SWIG的typemap需要先定义才能匹配目标类型)。
  • 检查SWIG编译命令是否正确,比如针对Python3编译需要指定-python参数,并链接正确的Python库。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:17:31