2012-02-20 53 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