我有一个用python编写的脚本。我正在将其细胞化,并将其作为C++模块插入。由此,我创建了dll,并将其连接到c#中的项目,其中库调用必须经过多次
问题恰恰出现在库的重复启动中,因为第一次处理脚本时,RAM没有被清除,这会阻止它重新启动。Python由占用大量内存的模块组成,因此单个使用该库需要160MB的RAM。 我尝试使用Py_Finalize(),但据我所知,他只为我删除了动态部分(~86MB),所以重新初始化结果是一个错误。如果不使用Py_Finalize(),那么每次重新启动都将占用+80-90MB的内存,在重复启动之后,这将成为一个非常大的问题
< P> C++库:运行Python 的方法void MLWrapper::outputInfo(char * curDirPath) {
auto err = PyImport_AppendInittab("runML", PyInit_runML);
wchar_t* szName = GetWC(curDirPath);
Py_SetPythonHome(szName);
Py_Initialize();
auto module = PyImport_ImportModule("runML");
mlDataG.predictionResult = runTab(&mlDataG);
Py_Finalize();}
C#:用于处理dll的类
public class ExternalHelpers : IDisposable
{
private IntPtr _libraryHandle;
private OutputInfoDelegate _outputInfo;
private delegate void OutputInfoDelegate([MarshalAs(UnmanagedType.LPStr)]string dirPath);
public ExternalHelpers()
{
_libraryHandle = UnsafeMethods.LoadLibrary("MLWrapper.dll");
if (_libraryHandle == IntPtr.Zero)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
_outputInfo = LoadExternalFunction<OutputInfoDelegate>(@"?outputInfo@MLWrapper@@YAXPEAD@Z") as OutputInfoDelegate;
}
public void OutputInfo(string path)
{
_outputInfo(path);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
~ExternalHelpers()
{
Dispose(false);
}
private Delegate LoadExternalFunction<Delegate>(string functionName)
where Delegate : class
{
IntPtr functionPointer =
UnsafeMethods.GetProcAddress(_libraryHandle, functionName);
if (functionPointer == IntPtr.Zero)
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
// Marshal to requested delegate
return Marshal.GetDelegateForFunctionPointer(functionPointer, typeof(Delegate)) as Delegate;
}
private void Dispose(bool disposing)
{
if (disposing)
{
_outputInfo = null;
}
if (_libraryHandle != IntPtr.Zero)
{
while (UnsafeMethods.FreeLibrary(_libraryHandle) == true)
{
continue;
}
//if (!UnsafeMethods.FreeLibrary(_libraryHandle))
// Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
_libraryHandle = IntPtr.Zero;
}
}
}
C#:方法调用
using (ExternalHelpers e = new ExternalHelpers())
{
...
e.OutputInfo(@"C:\Users\user\source\repos\Project\bin\x64\Debug");...}
我如何解决这个问题
我还想到了动态地重新连接库。因此,我可以完全关闭库并释放内存,但当您清除模块内存时,库将关闭,退出代码为:1,主应用程序结束
也许我忘了描述一些其他细节,所以如果需要更多信息,请在评论中更正我
您可以多次初始化/完成Python解释器,但这将导致内存泄漏。实际上,您应该在应用程序生命周期内只调用一次initialize/finalize。从
Py_FinalizeEx
[1]函数的Python文档中:参考文献:[1]https://docs.python.org/3/c-api/init.html#c.Py_FinalizeEx
有关此主题的更多信息:
Python bug tracker中报告了多个与此问题相关的bug。有朝一日,他们可能会修复CPython解释器本身的内存泄漏,但由加载的模块/库/扩展导致的内存泄漏将永远无法修复。例如,见:
A.https://bugs.python.org/issue1445210
B.https://bugs.python.org/issue1635741
相关问题 更多 >
编程相关推荐