2012-02-20 55 views
1

我打电话从C#这样的方法:妙传VC++到VC#一个ULONG64阵列和释放内存

[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位Long数组,并在使用它之后释放内存。如果它是由垃圾收集器管理的话,它会更好。

我试过Marshal.copy,但它没有工作,我恐怕会有一个mem泄漏(我不知道mem是否会自动释放)。任何帮助,将不胜感激。谢谢。

+2

改为传递数组作为参数。没有内存所有权的麻烦和不需要复制。 – 2012-02-20 14:50:43

+0

如果我使用参数传递指向日期的指针,我仍然必须在C#中释放它,对吗?我不知道这将如何解决我的问题? – Tormentor308 2012-02-20 18:12:37

+0

不,托管内存由垃圾回收器负责。 – 2012-02-20 18:16:21

回答

2

你有两种方法可以遵循:

  1. 添加“免费”功能,您的图书馆,并明确要求其对图书馆的侧分配每个资源。这需要库数量最少的代码更改,但您必须记住释放内存,除非您将为IntPtr创建一些IDisposable包装器,以便自动执行作业。例如,您可以使用此类:

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

编辑:作为第一个建议一个suppliment,你可以使用下面的类:

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