2015-12-01 45 views
1

我有一個C++函數,它接受一個數組(double *)作爲參數,對數據做些東西並返回一個類型爲complex *的指針指向相同的數據。我需要使用C++/cli來封裝這個函數,但是我不確定如何確保.NET以適當的內存引用結束。例如,如果用戶調用像這樣的函數Complex[] data = Process(new double[1024]);我想確保數據不會在函數返回時得到垃圾回收(並且我的pin_ptr超出範圍),並且它還會在data退出時收集垃圾回收範圍。 如何結束對內存的兩個有效引用,每個類型都是不同的? 注意:底層C++函數工作正常,這是一個.NET C++/CLI問題,關於如何將兩個垃圾收集引用移到兩個不同類型的同一內存中。取一個數組<double> ^並返回一個數組<Complex> ^指向同一個內存

#pragma unmanaged 
complex<double>* NativeFft(double* real_time_data, int data_size) { 
    // do in-place FFT on data (no allocations) 
    return reinterpret_cast<complex<double*>>(real_time_data); 
} 

#pragma managed 
array<Complex>^ Transform::Fft(array<double>^ real_time_data) { 
    if (real_time_data== nullptr) { 
     throw gcnew ArgumentNullException("'real_time_data' must not be null"); 
    } 
    int data_size = real_time_data->Length; 
    pin_ptr<double> data_ptr = &real_time_data[0]; 
    complex<double>* complex_freq_data = NativeFft(data_ptr, data_size); 
    // now how do I make another reference to the data? 
    // (I also need the Length field to be halved). 
    array<Complex>^ managed_complex_freq_data = ??? 
    return managed_complex_freq_data; 
} 

編輯: 下面是一些更多的信息,因爲大家都說明顯的解決方法就是複製數據。 我正在做的是一個非常大的真實到複雜的就地FFT。數據以雙數組的形式出現,並且基本上保持這種方式(顯然數值變化),但是在FFT完成之後,對數據的正確解釋是每對雙打構成單個的實部和虛部複雜的樣品。我想要做的FFT的大小對於32位系統來說太大了,但我不想盡可能地接近這一點,所以我不想犧牲執行副本所需的內存數據。我可以總是將數據作爲雙精度來處理,但能夠把它看作複雜的就好了,因爲這就是FFT之後的真實情況。

+1

這是一個託管類型('^'),所以你*不這樣做*。請閱讀[什麼是XY問題?](http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem)並相應地更改您的問題。 –

+0

函數返回後,'new double [1024]'應該被垃圾收集,因爲它不再需要。返回值應該由'data_out'構建(在調用'NativeProcess'後你用'data'完成,所以不知道爲什麼你認爲你需要使用相同的「內存」)。 – crashmstr

+0

我需要使用相同的內存,因爲數組的大小將盡可能大,我不會有空間將它複製到另一個數組,即使原始數據被破壞,因爲在短時間內兩個數組都會存在我將耗盡內存。 –

回答

0

我不確定從雙倍轉換爲複雜。是否有可能將double作爲基本類型轉換爲Complex,它是託管類型,而不創建新對象?如果你需要更多的細節,我可以找到它。

但任何方式:直到任何指針指向它時,您的數據纔會被收集。

+0

理論上可能的,實際上我不知道。在我的C++/CLI代碼中,我得到一個數組 ^,將其固定,然後將其固定到本機複合體 *。所以託管到本地(反之亦然)不是問題。在C#中,很容易對現有數組做一個新的引用(只是將其分配給它)。但是我不知道該如何做的是將這兩個操作合併在一起,在C++/CLI中創建一個新的引用,但使用不同的類型。關於你的第二點,有效的gc指針也是如此,但本機指針並非如此。如果我可以創建一個有效的指向數據的gc指針,我同意。 –

+0

正如我從這個問題所理解的那樣,你需要更多的「不丟失」指針,轉換數據的東西。這就是爲什麼我說「不確定」。關於代碼中的第二點,我們看到數組 **^**和數組 **^**,所以gc應該工作。 – Michail

1

我可能完全誤解了你的問題或你的要求,但是將本地數組的內容複製到託管數組中並讓GC完成它的工作並不簡單嗎?

#include <complex> 

using namespace System; 
using namespace System::Numerics; 

std::complex<double>* NativeProcess(double* data, int& size); 

public ref class Processor 
{ 
public: 
    array<Complex>^ Processor::Process(array<double>^ data) 
    { 
     if (data == nullptr) 
      throw gcnew ArgumentNullException("data"); 

     int length = data->Length; 
     pin_ptr<double> dataPtr = &data[0]; 
     std::complex<double>* dataOut = NativeProcess(dataPtr, length); 

     array<Complex>^ complexArray = gcnew array<Complex>(length); 
     for (int idx = 0; idx < length; ++idx) 
      complexArray[idx] = Complex(dataOut[idx].real(), dataOut[idx].imag()); 

     delete[] dataOut; 
     return complexArray; 
    } 
}; 
+0

對於64位版本的軟件複製將起作用。對於32位版本不是那麼多。基本上它是完全內存綁定的,所以拷貝會削減我可以使用的一半數組的大小。 –