Как реализовать обратный вызов C#, совместимый с указателем функции Variadic библиотеки C++ для Unity ⇐ C++
-
Гость
Как реализовать обратный вызов C#, совместимый с указателем функции Variadic библиотеки C++ для Unity
Я работаю с библиотекой динамической компоновки C++ из xatlas, которая экспортирует функцию со следующей сигнатурой: __declspec(dllexport) void xatlasSetPrint(xatlasPrintFunc print, bool verbose);. xatlasPrintFunc определяется как typedef int (*xatlasPrintFunc)(const char *, ...);, что указывает на то, что он принимает переменное количество аргументов, аналогично C < функция code>printf. Моя цель — использовать эту функцию из C#, в частности, для установки функции обратного вызова печати в Unity (где моя версия C# ограничена стандартом C# 9 и .NET 2.1), но я сталкиваюсь с проблемами из-за вариативного характера функции. указатель. Я предпочитаю не писать дополнительную библиотеку адаптеров C++, чтобы сохранить краткость проекта.
Учитывая указатель на переменную функцию в C++ и мои требования в C#, как я могу точно определить и реализовать обратный вызов C#, совместимый с этой функцией C++ DLL? Существует ли эффективный способ обработки переменных аргументов из C++ в C# или мне следует рассмотреть другой подход?
Кроме того, я стремлюсь в конечном итоге регистрировать сообщения с помощью UnityEngine.Debug.Log, поэтому идеальными будут решения, совместимые с ограничениями Unity. Если добиться этого напрямую нецелесообразно, я готов использовать другую собственную библиотеку, чтобы исправить количество параметров, но предпочел бы более простое решение.
Причина закрытия не может работать напрямую, но она вдохновила меня, это работает (отредактируйте: это работает только в некоторых случаях, в большинстве случаев это не работает):
с использованием AOT; использование системы; использование System.Runtime.InteropServices; общедоступный статический класс PrintFormat { const string msvcrtDll = "msvcrt.dll"; [MonoPInvokeCallback(typeof(PrintFunc))]//Для il2cpp, в противном случае необязательно public unsafe static int Printf (IntPtr PStr_format, byte args) { int count = _vscprintf(PSt_format, ref args) + 1; var buffer = stackalloc byte[count]; IntPtr pbuffer = (nint)буфер; int retcode = vsprintf(pbuffer, PStr_format, ref args); /*-----Вот что я хочу------*/ Console.Write(Marshal.PtrToStringAnsi(pbuffer)); вернуть реткод; } [DllImport(msvcrtDll, CallingConvention = CallingConvention.Cdecl)] public static extern int vsprintf (буфер IntPtr, IntPtr PStr_format, ref byte args); [DllImport(msvcrtDll, CallingConvention = CallingConvention.Cdecl)] public static extern int _vscprintf (IntPtr PStr_format, ref byte args); } API C# P/Invoke:
[UnmanagedFunctionPointer(Cdecl)] публичный делегат int PrintFunc (IntPtr PStr_format, byte args); [DllImport(DLL,CallingConvention=Cdecl,EntryPoint="xatlasSetPrint")] public static extern void SetPrint (PrintFunc print, BOOL многословный); использование:
SetPrint(PrintFormat.Printf, true); для закрытия: повторяющийся вопрос не работает, в первом ответе нет возможности использования собственного управляемого обратного вызова, второй ответ вообще не работает. CIL... Я бы предпочел вместо этого создать другую библиотеку-оболочку. И мой обходной путь все еще не работает.
Я работаю с библиотекой динамической компоновки C++ из xatlas, которая экспортирует функцию со следующей сигнатурой: __declspec(dllexport) void xatlasSetPrint(xatlasPrintFunc print, bool verbose);. xatlasPrintFunc определяется как typedef int (*xatlasPrintFunc)(const char *, ...);, что указывает на то, что он принимает переменное количество аргументов, аналогично C < функция code>printf. Моя цель — использовать эту функцию из C#, в частности, для установки функции обратного вызова печати в Unity (где моя версия C# ограничена стандартом C# 9 и .NET 2.1), но я сталкиваюсь с проблемами из-за вариативного характера функции. указатель. Я предпочитаю не писать дополнительную библиотеку адаптеров C++, чтобы сохранить краткость проекта.
Учитывая указатель на переменную функцию в C++ и мои требования в C#, как я могу точно определить и реализовать обратный вызов C#, совместимый с этой функцией C++ DLL? Существует ли эффективный способ обработки переменных аргументов из C++ в C# или мне следует рассмотреть другой подход?
Кроме того, я стремлюсь в конечном итоге регистрировать сообщения с помощью UnityEngine.Debug.Log, поэтому идеальными будут решения, совместимые с ограничениями Unity. Если добиться этого напрямую нецелесообразно, я готов использовать другую собственную библиотеку, чтобы исправить количество параметров, но предпочел бы более простое решение.
Причина закрытия не может работать напрямую, но она вдохновила меня, это работает (отредактируйте: это работает только в некоторых случаях, в большинстве случаев это не работает):
с использованием AOT; использование системы; использование System.Runtime.InteropServices; общедоступный статический класс PrintFormat { const string msvcrtDll = "msvcrt.dll"; [MonoPInvokeCallback(typeof(PrintFunc))]//Для il2cpp, в противном случае необязательно public unsafe static int Printf (IntPtr PStr_format, byte args) { int count = _vscprintf(PSt_format, ref args) + 1; var buffer = stackalloc byte[count]; IntPtr pbuffer = (nint)буфер; int retcode = vsprintf(pbuffer, PStr_format, ref args); /*-----Вот что я хочу------*/ Console.Write(Marshal.PtrToStringAnsi(pbuffer)); вернуть реткод; } [DllImport(msvcrtDll, CallingConvention = CallingConvention.Cdecl)] public static extern int vsprintf (буфер IntPtr, IntPtr PStr_format, ref byte args); [DllImport(msvcrtDll, CallingConvention = CallingConvention.Cdecl)] public static extern int _vscprintf (IntPtr PStr_format, ref byte args); } API C# P/Invoke:
[UnmanagedFunctionPointer(Cdecl)] публичный делегат int PrintFunc (IntPtr PStr_format, byte args); [DllImport(DLL,CallingConvention=Cdecl,EntryPoint="xatlasSetPrint")] public static extern void SetPrint (PrintFunc print, BOOL многословный); использование:
SetPrint(PrintFormat.Printf, true); для закрытия: повторяющийся вопрос не работает, в первом ответе нет возможности использования собственного управляемого обратного вызова, второй ответ вообще не работает. CIL... Я бы предпочел вместо этого создать другую библиотеку-оболочку. И мой обходной путь все еще не работает.
Мобильная версия