Как реализовать обратный вызов C#, совместимый с указателем функции Variadic библиотеки C++ для UnityC++

Программы на 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... Я бы предпочел вместо этого создать другую библиотеку-оболочку. И мой обходной путь все еще не работает.
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»