除了通过 mex 文件 mexAtExit 处理程序之外,我是否可以检测 MATLAB 终止?
Can I detect MATLAB termination other than by way of a mex file mexAtExit handler?
tl;dr
在 Matlab .m 文件中是否有任何方法可以检测正在进行的 Matlab 终止?
我有一个为我的产品提供接口的非托管库。我已经使用 mex 文件为 Matlab 包装了它。所以我的非托管库作为 Windows DLL 存在。我有一个包装它的 mex 文件。反过来,我有一个 Matlab 类 的集合,在包装 mex 文件的各种 .m 文件中实现。到目前为止一切顺利,所有这些都非常出色。
我最近意识到 Matlab 关闭期间的一个问题。一些 Matlab 类 包装非托管对象。这些非托管对象在不再需要时需要销毁。因此,我为包装非托管对象的 Matlab 类 实现了 delete
函数,并调用 mex 文件来销毁这些对象。显然,mex 文件只是将这些销毁调用转发给非托管库。同样,这一切都很好。
当 Matlab 关闭并且用户的工作区包含包装非托管对象的 Matlab 对象时,就会出现问题。不幸的是,Matlab 卸载了 mex 文件,然后破坏了工作区中的对象。接下来发生的是 delete
函数执行调用 mex 文件。重新加载刚刚卸载的 mex 文件。现在试图销毁非托管对象会导致运行时错误,因为我的库必须重新加载。
由于要在销毁工作区对象之前卸载 mex 文件,我别无选择,只能跳过该场景中非托管对象的删除。这不是内存泄漏,也不是任何方面的问题,因为进程正在终止。但是,我确实需要检测到进程正在终止。这就引出了一个问题,如何做到这一点。
我知道 finish.m
终止文件,但我无法控制它,因为我提供了一个库。用户控制他们的终止文件,因此我排除了该选项。我什至不知道它是否在合适的时间运行,即在工作区对象被销毁之前。
我已经使用 mexAtExit
构建了一个有效的解决方案。在 mex 文件初始化中,我这样调用 mexAtExit
:
mexAtExit(atExit);
atExit
函数是:
void atExit(void)
{
mexCallMATLAB(0, NULL, 0, NULL, "mylib.atExit");
}
而ofx.atExit
在Matlab代码中是这样实现的:
methods(Static)
function atExit
mylib.mexHasUnloaded(true);
end
function result = mexHasUnloaded(varargin)
global mexHasUnloadedGlobalVar;
if isempty(mexHasUnloadedGlobalVar)
mexHasUnloadedGlobalVar = false;
end
if nargin > 0
mexHasUnloadedGlobalVar = varargin{1};
end
result = mexHasUnloadedGlobalVar;
end
....
end
delete
函数然后像这样检查 mexHasUnloaded
:
function delete(self)
if ~mylib.mexHasUnloaded
mylibMex(mylib.mexDestroyObject, self.handle);
end
end
虽然这似乎有效,但我对此一点都不满意。
- 我真的只能从 mex 文件中检测 Matlab 终止吗?我想直接在 .m 文件中检测到这一点,感觉应该是可能的。可能吗?
- 我真的需要使用这样的全局变量吗?我不能找到更好的方法来照顾这种状态吗?我尝试使用
persistent
变量,但这同样很老套而且没有用。 persistent
变量在终止期间的某个时刻被重新初始化,这意味着 mexHasUnloaded
在之前被设置为 true
. 之后开始返回 false
- 或者我的问题有不同的解决方案吗?我可以强制我的 mex 文件保持加载状态直到工作区对象被删除吗?
它是否适用于 mexLock()
您的 MEX 文件,以便它不会被卸载,所以 delete
方法可以在关闭时做正确的事情?
tl;dr
在 Matlab .m 文件中是否有任何方法可以检测正在进行的 Matlab 终止?
我有一个为我的产品提供接口的非托管库。我已经使用 mex 文件为 Matlab 包装了它。所以我的非托管库作为 Windows DLL 存在。我有一个包装它的 mex 文件。反过来,我有一个 Matlab 类 的集合,在包装 mex 文件的各种 .m 文件中实现。到目前为止一切顺利,所有这些都非常出色。
我最近意识到 Matlab 关闭期间的一个问题。一些 Matlab 类 包装非托管对象。这些非托管对象在不再需要时需要销毁。因此,我为包装非托管对象的 Matlab 类 实现了 delete
函数,并调用 mex 文件来销毁这些对象。显然,mex 文件只是将这些销毁调用转发给非托管库。同样,这一切都很好。
当 Matlab 关闭并且用户的工作区包含包装非托管对象的 Matlab 对象时,就会出现问题。不幸的是,Matlab 卸载了 mex 文件,然后破坏了工作区中的对象。接下来发生的是 delete
函数执行调用 mex 文件。重新加载刚刚卸载的 mex 文件。现在试图销毁非托管对象会导致运行时错误,因为我的库必须重新加载。
由于要在销毁工作区对象之前卸载 mex 文件,我别无选择,只能跳过该场景中非托管对象的删除。这不是内存泄漏,也不是任何方面的问题,因为进程正在终止。但是,我确实需要检测到进程正在终止。这就引出了一个问题,如何做到这一点。
我知道 finish.m
终止文件,但我无法控制它,因为我提供了一个库。用户控制他们的终止文件,因此我排除了该选项。我什至不知道它是否在合适的时间运行,即在工作区对象被销毁之前。
我已经使用 mexAtExit
构建了一个有效的解决方案。在 mex 文件初始化中,我这样调用 mexAtExit
:
mexAtExit(atExit);
atExit
函数是:
void atExit(void)
{
mexCallMATLAB(0, NULL, 0, NULL, "mylib.atExit");
}
而ofx.atExit
在Matlab代码中是这样实现的:
methods(Static)
function atExit
mylib.mexHasUnloaded(true);
end
function result = mexHasUnloaded(varargin)
global mexHasUnloadedGlobalVar;
if isempty(mexHasUnloadedGlobalVar)
mexHasUnloadedGlobalVar = false;
end
if nargin > 0
mexHasUnloadedGlobalVar = varargin{1};
end
result = mexHasUnloadedGlobalVar;
end
....
end
delete
函数然后像这样检查 mexHasUnloaded
:
function delete(self)
if ~mylib.mexHasUnloaded
mylibMex(mylib.mexDestroyObject, self.handle);
end
end
虽然这似乎有效,但我对此一点都不满意。
- 我真的只能从 mex 文件中检测 Matlab 终止吗?我想直接在 .m 文件中检测到这一点,感觉应该是可能的。可能吗?
- 我真的需要使用这样的全局变量吗?我不能找到更好的方法来照顾这种状态吗?我尝试使用
persistent
变量,但这同样很老套而且没有用。persistent
变量在终止期间的某个时刻被重新初始化,这意味着mexHasUnloaded
在之前被设置为true
. 之后开始返回 - 或者我的问题有不同的解决方案吗?我可以强制我的 mex 文件保持加载状态直到工作区对象被删除吗?
false
它是否适用于 mexLock()
您的 MEX 文件,以便它不会被卸载,所以 delete
方法可以在关闭时做正确的事情?