vb.net byte [] в C ++ char * - PullRequest
       10

vb.net byte [] в C ++ char *

2 голосов
/ 05 ноября 2008

Я вызываю неуправляемую DLL C ++, которая ожидает символ * в качестве одного из своих параметров, и я хочу вставить в нее байт []. Проект написан на VB.NET.

Какой тип сортировки будет работать для этого?

Ответы [ 3 ]

1 голос
/ 05 ноября 2008

Если вам нужно закрепить управляемую структуру, чтобы передать ее в качестве параметра, вы можете использовать следующий код.

    // (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 голосов
/ 21 ноября 2009

В вашем определении PInvoke просто объявите параметр char * как байт [], и стандартный маршаллер будет обрабатывать работу.

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

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

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

0 голосов
/ 05 ноября 2008

Я не эксперт по .net, но недавно мне нужно было сделать нечто подобное.

Это не просто вопрос сериализации, вы также должны помешать сборщику мусора очистить ваш байтовый массив, пока он используется в C ++ land ...

Следующий фрагмент кода 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();
...