2011-01-12 56 views
4

我想調用一個方法,我有C++頭的dll。我從C#調用dll。輸入是一個字符串,輸出是二進制數據。以下3種方法中的任何一種都可能起作用,我只是不知道如何使它們中的任何一種都起作用。由於我的C#聲明,所以他們可能不正確從C調用dll與C++頭#

1:我能夠得到hGlobal,但我不知道如何從句柄中獲取數據。

//CMBT_LL_WINAPI INT DLLPROC LlConvertStringToHGLOBALW(LPCWSTR pszText, _PHGLOBAL phMemory); 
[DllImport("cmll15.dll", EntryPoint = "LlConvertStringToHGLOBALW", CharSet = CharSet.Unicode, ExactSpelling = true)] 
private static extern int _LlConvertStringToHGlobal32(string text, ref IntPtr handle); 

2:

[DllImport("cmll15.dll", EntryPoint = "LlConvertStringToBLOBW", CharSet = CharSet.Unicode, ExactSpelling = true)] 
//CMBT_LL_WINAPI INT  DLLPROC LlConvertStringToBLOBW(LPCWSTR pszText, _PUINT8 pBytes, UINT nBytes); 
private static extern int _LlConvertStringToBLOBW(string text, ref IntPtr pBytes, UInt32 nBytes); 

3:

[DllImport("cmll15.dll", EntryPoint = "LlConvertStringToStreamW", CharSet = CharSet.Unicode, ExactSpelling = true)] 
//CMBT_LL_WINAPI INT  DLLPROC LlConvertStringToStreamW(LPCWSTR pszText, _PISTREAM pStream); 
private static extern int _LlConvertStringToStreamW(string text, ref IntPtr pStream); 

更新,這裏就是我想我會在最後的代碼。

[DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] 
    private static extern UIntPtr GlobalSize(IntPtr hMem); 

    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] 
    public static extern IntPtr GlobalLock(IntPtr handle); 

    [DllImport("kernel32.dll", SetLastError = true, ExactSpelling = true)] 
    public static extern IntPtr GlobalUnlock(IntPtr handle); 

    [DllImport("cmll15.dll", EntryPoint = "LlConvertStringToHGLOBALW", CharSet = CharSet.Unicode, ExactSpelling = true)] 
    private static extern int _LlConvertStringToHGlobal32(string text, ref IntPtr handle); 

    private static void Main(string[] args) 
    { 
     IntPtr dataHandle = IntPtr.Zero; 
     _LlConvertStringToHGlobal32(Contents, ref dataHandle); 
     try 
     { 
      var size = (uint) GlobalSize(dataHandle); 
      var array = new byte[size]; 
      IntPtr dataPtr = GlobalLock(dataHandle); 
      try 
      { 
       Marshal.Copy(dataPtr, array, 0, array.Length); 
      } 
      finally 
      { 
       GlobalUnlock(dataPtr); 
      } 

      using (var fs = new FileStream("c:\\file.dat", FileMode.Create)) 
      { 
       fs.Write(array, 0, array.Length); 
      } 
     } 
     finally 
     { 
      Marshal.FreeHGlobal(dataHandle); 
     } 
    } 
+0

你試過編譯和運行它們嗎?指定問題以便我們理解。 – Nawaz 2011-01-12 09:01:24

+1

如果您已經指定了`CharSet.Unicode`,爲什麼還要指定`ExactSpelling`和`EntryPoint`?那些是多餘的。 – 2011-01-12 09:06:19

+0

我不認爲我的問題是將方法從C++轉換爲C#,但我不知道,我只是向他們展示了它們,因此您可能會發現任何錯誤。我認爲C#簽名是正確的,但我現在不知道調用方法或使用方法 – Karsten 2011-01-12 09:23:37

回答

1

第一個應該是最容易開始,因爲這留給被調查者來確定所需的大小。然而,不知道你應該怎麼知道分配的大小。也許是返回值。您始終可以調用GlobalSize()以從HGLOBAL句柄中獲取大小。您應該調用GlobalLock()將句柄轉換爲指針,然後Marshal.CopyMemory()將其複製到byte []中。通過調用GlobalUnlock()和Marshal.FreeHGlobal()來釋放內存,將其放入一個finally塊中以便不會泄漏。

對於第二個,你應該聲明第二個參數爲byte [](不是參考)。麻煩的是,你必須預先猜測陣列的大小。失敗模式會猜測這個尺寸太小。

第三個需要COM IStream。聲明它爲System.Runtime.InteropServices.ComTypes.IStream。它的行爲很像.NET Stream,你可以調用Seek來尋找開始,閱讀來讀取數據。

我會爲第一個去,最不可能爆炸在你的臉上。

-1

在1: 你應該有二進制數據輸出的長度,然後用Marshal.Copy方法如下: 字節[]數據=新的字節[長度]; Marshal.Copy(handle,data,0,length);

For 2 & 3:你有什麼問題?