2008-11-05 2 views
2

Я вызываю неуправляемую DLL C++, которая ожидает, что 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 просто объявить символ * параметр как байт [] и стандартной ИАС будет обрабатывать работу.

Но это может быть или не быть лучшей идеей. Является ли функция C++ ожидающей строки или ожидает буфера данных (код C/C++ часто использует char * для буфера, полагаясь на то, что char является одним байтом)?

Если это буфер, то байт [] определенно правильный, но если он ожидает строку, то может быть яснее, если вы объявите параметр как строку (явную) и используйте Encoding.ASCII.GetString () для преобразования байта [] в строку.

Также, если функция C++ ожидает строку, и вы решите объявить этот параметр как байт [], убедитесь, что массив байтов заканчивается нулем, так как это означает, что C/C++ определяет конец строки.