我正在调用C#中的一个方法:
[DllImport(@"C:\Hash.dll",
CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr ph_dct_videohash(
string file,
ref int length);
static void Main(string[] args)
{
int length = 0;
ph_dct_videohash(@"C:\Users\shady\H.avi", ref length);
Console.Read();
}
这是我从库中调用的方法
ulong64* ph_dct_videohash(const char *filename, int &Length){
CImgList<uint8_t> *keyframes = ph_getKeyFramesFromVideo(filename);
if (keyframes == NULL)
return NULL;
Length = keyframes->size();
ulong64 *hash = (ulong64*)malloc(sizeof(ulong64)*Length);
//some code to fill the hash array
return hash;}
问题是如何在C#中检索无符号64位长数组并在使用后释放内存。如果它由我的垃圾收集器管理会更好。
我尝试了Marshal.copy,但它没有用,我担心会有内存泄漏(我不知道内存是否会被自动释放)。任何帮助,将不胜感激。谢谢。
答案 0 :(得分:2)
您可以采用以下两种方式:
将“免费”功能添加到您的库并为库侧分配的每个资源显式调用它。这需要库侧的代码更改量最少,但您必须记住关于释放内存,除非你为IDisposable
创建一些自动完成工作的IntPtr
包装器。例如,您可以使用此类:
更改公共库的函数以接受指向缓冲区的指针,而不是在内部分配它们。这可能需要对库侧进行大量更改,但会简化C#端的代码。
编辑:作为第一个建议的补充,您可以使用以下课程:
public class HashDllAutoPtr : IDisposable
{
[DllImport(@"C:\Hash.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern void ph_dct_free(IntPtr ptr);
public HashDllAutoPtr(IntPtr ptr)
{
Ptr = ptr;
}
~HashDllAutoPtr()
{
Dispose();
}
public IntPtr Ptr
{
get;
private set;
}
#region IDisposable Members
public void Dispose()
{
if (Ptr != IntPtr.Zero)
{
ph_dct_free(Ptr);
}
Ptr = IntPtr.Zero;
}
#endregion
}
只需为每个IntPtr结果创建一个实例。然后,您可以在需要释放内存时手动调用Dispose
,或者您可以将其挂起并最终由GC拾取(尽管我不推荐它)。您可以阅读有关处理非托管数据here