2008-11-05 93 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++如何确定字符串的末尾。