PInvoke и представление параметра void** в управляемом коде - C#
Формулировка задачи:
Здравствуйте!
Проблема состоит в следующем:
В библиотеке на CPP имеется некая функция, которая устанавливает соответствующие колбэки, а так же определена сигнатура этих колбэков, что-то вроде такого:
На С++ тело колбэка должно выглядеть следующим образом:
Так вот вопрос в том, как сделать нечто такое на C#?:
Сейчас это выглядит следующим образом:
В Buffer1 я пробовал выделять память с помощью Marshal а так же с помощью GCHandle, но, на сколько я понял, просто записать в _buf ссылку не достаточно.
Как правильно это делается?
п.с., если интерестно, то это библиотека LibVlc. И тут я описал не все, а только то что поможет в достаточной мере раскрыть проблему.
typedef void *(*lock)(void **buf); extern "C" __declspec ( dllexport ) void set_callbacks(lock _lock);
unsigned char * pixels; //инициализируется где-то в коде, и является массивом определенного размера ........ void *lock(void **buf) { *buf = pixels; return NULL; }
void **buf *buf = pixels;
public static class myLib { [DllImport("Library.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void set_callbacks(lock_cb _lock); public delegate IntPtr lock_cb(ref IntPtr _buf); } ..... static IntPtr cbLock(ref IntPtr _buf) { _buf= Buffer1; //Buffer1 это IntPtr в котором находится ссылка на область памяти в неуправляемой куче return IntPtr.Zero; } ..... myLib.set_callbacks(cbLock);
Решение задачи: «PInvoke и представление параметра void** в управляемом коде»
textual
Листинг программы
using System; using System.Linq; using System.Runtime.InteropServices; namespace ConsoleApplication1 { static class Program { [DllImport(@"Library.dll", EntryPoint = @"set_callbacks", CallingConvention = CallingConvention.Cdecl)] public static extern void SetCallback(CallbackHandler _lock); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate IntPtr CallbackHandler(IntPtr data); static void Main() { SetCallback(Callback); TEST(); _currentCallbackHandle.Free(); } static IntPtr Callback(IntPtr buf) { var arr = ToByteArray(buf); var flat = Flatten(arr); _currentCallbackHandle = GCHandle.Alloc(flat, GCHandleType.Pinned); // !! return _currentCallbackHandle.AddrOfPinnedObject(); } // TEST static GCHandle _currentCallbackHandle; [DllImport(@"Library.dll", CallingConvention = CallingConvention.Cdecl)] public static extern void TEST(); static byte[][] ToByteArray(IntPtr buf) { var l1p = new IntPtr[2]; Marshal.Copy(buf, l1p, 0, l1p.Length); var arr = new byte[2][]; for (int k = 0; k < arr.Length; k++) Marshal.Copy(l1p[k], arr[k] = new byte[4], 0, arr[k].Length); return arr; } static byte[] Flatten(byte[][] arr) { var result = new byte[arr.Sum(t => t.Length)]; for (int i = 0, c = 0; i < arr.Length; i++) { arr[i].CopyTo(result, c); c += arr[i].Length; } return result; } } }
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д