SWIG:从 python 返回的模板给出"memory leak no destructor found"警告



我有一些python函数,我从c++端运行,我需要它们返回std::预期对象。我所做的是:

def do_operation(self):
print("Operation done")
return void_expected()

在Swig代码中,我有如下内容:

%inline %{
std::expected<void, OperationError> void_expected()
{
return std::expected<void, OperationError>{};
}
%}
%typemap(out) std::expected<void, OperationError> {
if (!$1.has_value()) {
SWIG_exception(SWIG_RuntimeError, "Unexpected error!");
}
Py_RETURN_NONE;
}

但是我得到所有这些警告运行python脚本:

swig/python detected a memory leak of type 'std::expected< void,OperationError > *', no destructor found.

您看到的错误消息提示正在发生什么。虽然我以前对这个警告的回答在这里确实适用,但它不应该适用,这暗示了哪里出了问题。您期望的行为是,对于在c++中返回值的情况,None在Python中返回。相反,如果期望对象中没有值,则会引发Python异常。在这两种情况下,您都不期望SWIG在Python端为std::expected结果创建代理对象。

因此,您看到这个警告的事实表明,在您编写的接口中有些东西不像预期的那样。事实证明它相当简单——您展示的typemap在之后出现,这是预期使用它的地方。所以它不会被应用

我们可以通过构造一个小的、完整的例子来证实这一点:

%module test
%include <exception.i>
%{
#include "expected.h" // TODO: include <expected>  insteadwhen I really have C++23 impl 
%}

%typemap(out) std::expected<void, OperationError> {
if (!$1.has_value()) {
SWIG_exception(SWIG_RuntimeError, "Unexpected error!");
}
Py_RETURN_NONE;
}
%inline %{
class OperationError {};
std::expected<void, OperationError> void_expected() {
return std::expected<void, OperationError>{};
}
%}

(由于手头没有c++ 23编译器,我不得不自己编写expect .h !)

// Minimal parts needed to prove the point with this answer
namespace std {
template <typename T, typename E>
struct expected {
bool has_value() const { return true; }
};
}

和一些Python来证明它:

import test
test.void_expected()

我们可以这样构建和运行:

swig3.0 -c++ -python -py3 test.i
g++ -shared -Wall -Wextra test_wrap.cxx  -I/usr/include/python3.7 -m32 -o _test.so 
python3 run.py

运行时没有错误。交换类型映射和%inlinevoid_expected()声明/定义的顺序,但是在你的问题中,你会看到完全相同的错误,因为类型映射没有得到应用。


最新更新