2008-11-05 119 views
2

我在調用一個非託管C++ dll,期望char *作爲其參數之一,並且我想將一個字節[]插入它。該項目是用VB.NET編寫的。vb.net byte [] to C++ char *

什麼類型的編組將爲此工作?

回答

0

我不是.net專家,但我最近需要做類似的事情。

它不只是一個系列化的事,你也不得不從,而它在C++的土地被用來清理你的字節數組停止垃圾收集器...

的C#以下代碼段應該有所幫助。

// pin the byte[] (byteArray) 
GCHandle handle = GCHandle.Alloc(byteArray, GCHandleType.Pinned); 
IntPtr address = handle.AddrOfPinnedObject(); 
// Do your C++ stuff, using the address pointer. 

// Cleanup 
handle.Free();
1

如果您需要固定託管結構以將其作爲參數傳遞,則可以使用以下代碼。

// (c) 2007 Marc Clifton 
    /// <summary> 
    /// A helper class for pinning a managed structure so that it is suitable for 
    /// unmanaged calls. A pinned object will not be collected and will not be moved 
    /// by the GC until explicitly freed. 
    /// </summary> 

    internal class PinnedObject<T> : IDisposable where T : struct 
    { 
     protected T managedObject; 
     protected GCHandle handle; 
     protected IntPtr ptr; 
     protected bool disposed; 

     public T ManangedObject 
     { 
      get 
      { 
       return (T)handle.Target; 
      } 
      set 
      { 
       Marshal.StructureToPtr(value, ptr, false); 
      } 
     } 

     public IntPtr Pointer 
     { 
      get { return ptr; } 
     } 

     public int Size 
     { 
      get { return Marshal.SizeOf(managedObject); } 
     } 

     public PinnedObject() 
     { 
      managedObject = new T(); 
      handle = GCHandle.Alloc(managedObject, GCHandleType.Pinned); 
      ptr = handle.AddrOfPinnedObject(); 
     } 

     ~PinnedObject() 
     { 
      Dispose(); 
     } 

     public void Dispose() 
     { 
      if (!disposed) 
      { 
       if (handle.IsAllocated) 
        handle.Free(); 
       ptr = IntPtr.Zero; 
       disposed = true; 
      } 
     } 
    } 
} 

然後,您可以使用PinnedObject.Pointer調用非託管代碼。在你的extern聲明中,使用IntPtr作爲該參數的類型。

PinnedObject<BatteryQueryInformation> pinBatteryQueryInfo = new PinnedObject<BatteryQueryInformation>(); 
pinBatteryQueryInfo.ManangedObject = _structBatteryQueryInfo; 
Unmanaged.Method(pinBatteryQueryInfo.Pointer); 
0

在您的PInvoke定義中,只需將char *參數聲明爲byte [],標準編組將處理工作。

但這可能是也可能不是最好的主意。 C++函數需要一個字符串還是期待一個數據緩衝區(C/C++代碼通常使用char *作爲緩衝區,依賴於char是一個字節的事實)?

如果它是一個緩衝區,那麼一個字節[]當然是正確的,但如果它期望一個字符串,那麼它可能會更清晰,如果你聲明參數爲一個字符串(顯式),並使用Encoding.ASCII.GetString )將字節[]轉換爲字符串。

此外,如果它的C++函數需要字符串並決定聲明參數作爲字節[],確保字節數組具有零結束,因爲這是C/C++如何確定字符串的末尾。