2013-10-04 66 views
1

作爲我之前問題的後續工作,我最終得到了C dll導出並可在C#中使用,但我試圖弄清楚正確的參數類型並調用方法。確定DLLImport參數並安全地調用非託管C函數

我在這裏研究過SO,但似乎沒有一個模式來指定變量類型。

我看到一些人建議爲uchar*一個StringBuilder,別人byte[],以「不安全」的代碼中的一些參考等誰能推薦在此基礎上具體使用情況的解決方案?

還要注意現在代碼立即生成的異常,就在調用C函數之後。

C函數進口:

[DllImport("LZFuncs.dll")] 
internal static extern long LZDecomp(ref IntPtr outputBuffer, byte[] compressedBuffer, UInt32 compBufferLength); //Originally two uchar*, return is size of uncompressed data. 

C函數簽名:

long LZDecomp(unsigned char *OutputBuffer, unsigned char *CompressedBuffer, unsigned long CompBufferLength) 

使用如下:

for (int dataNum = 0; dataNum < _numEntries; dataNum++) 
     { 
      br.BaseStream.Position = _dataSizes[dataNum]; //Return to start of data. 
      if (_compressedFlags[dataNum] == 1) 
      { 
       _uncompressedSize = br.ReadInt32(); 
       byte[] compData = br.ReadBytes(_dataSizes[dataNum] - 4); 
       IntPtr outData = IntPtr.Zero; 
       LZFuncs.LZDecomp(ref outData, compData, Convert.ToUInt32(compData.Length)); 
       var uncompData = new byte[_uncompressedSize]; //System.ExecutionEngineException was unhandled 
       Marshal.Copy(outData, uncompData, 0, Convert.ToInt32(_uncompressedSize)); 
       BinaryWriter bw = new BinaryWriter(new FileStream("compData" + dataNum + ".txt", FileMode.CreateNew)); 
       bw.Write(uncompData); 
       bw.Close(); 
      } 
      else 
      { 
       BinaryWriter bw = new BinaryWriter(new FileStream("uncompData" + dataNum + ".txt", FileMode.CreateNew)); 
       bw.Write(br.ReadBytes(_dataSizes[dataNum])); 
       bw.Close(); 
      } 
     } 

我假設C代碼是相當嚴重的,如果它是重挫內存用這樣的CLR異常打破C#調用者,但由於C代碼的寫法,絕對沒有辦法修改它而不會破壞功能,它實際上是一個黑匣子。 (用匯編寫的,在大多數情況下)。

僅供參考,只是我一直在努力讀了一些問題,這個解決自己:

How do I return a byte array from C++ to C#

Correct way to marshall uchar[] from native dll to byte[] in c#

有已成爲其他人,但這些是最近的。

回答

1

好的,這並不難。兩個緩衝區參數是字節數組。你應該聲明它們爲byte[]。調用約定是Cdecl。請記住,C++ long在Windows上只有32位寬,所以使用C#int而不是C#long,因爲後者是64位寬。

聲明函數是這樣的:

[DllImport("LZFuncs.dll", CallingConvention = CallingConvention.Cdecl)] 
internal static extern int LZDecomp(
    [Out] byte[] outputBuffer, 
    [In] byte[] compressedBuffer, 
    uint compBufferLength 
); 

您解壓compressedBufferoutputBuffer。您需要知道需要多大的outputBuffer(問題中的代碼顯示您已經處理了這個問題)並分配了一個足夠大的數組。除此之外,我認爲這很明顯。

調用代碼將這個樣子的:

_uncompressedSize = br.ReadInt32(); 
byte[] compData = br.ReadBytes(_dataSizes[dataNum] - 4); 
byte[] outData = new byte[_uncompressedSize]; 
int len = LZFuncs.LZDecomp(outData, compData, (uint)compData.Length); 
+0

謝謝你,那確實起作用。我認爲C++ long在代碼中的其他地方長度不同,但不在導入中。同時在修復了您發佈的代碼後,在我使用_dataSizes而不是_dataOffset的原始代碼中發現了錯誤完美。非常感激! – Tigress

相關問題