将ulong64数组从VC ++传递到VC#并释放内存

时间:2012-02-20 14:10:55

标签: c# interop pinvoke

我正在调用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,但它没有用,我担心会有内存泄漏(我不知道内存是否会被自动释放)。任何帮助,将不胜感激。谢谢。

1 个答案:

答案 0 :(得分:2)

您可以采用以下两种方式:

  1. 将“免费”功能添加到您的库并为库侧分配的每个资源显式调用它。这需要库侧的代码更改量最少,但您必须记住关于释放内存,除非你为IDisposable创建一些自动完成工作的IntPtr包装器。例如,您可以使用此类:

  2. 更改公共库的函数以接受指向缓冲区的指针,而不是在内部分配它们。这可能需要对库侧进行大量更改,但会简化C#端的代码。

  3. 编辑:作为第一个建议的补充,您可以使用以下课程:

    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

    的更多信息