1. Ты берёшь указатель на переменную на стеке, которая после выхода из него уже не факт, что будет иметь то значение, которое тебе нужно.
2. Тебе нужно выделить память заранее (или в куче) и в эту область памяти уже записывать результат.
3. Лучше, чтобы память для результата выделялась на стороне C#, чтобы не было проблем с освобождением памяти.
4. Сишный int не всегда равен шарповому int.
5. В .NET уже есть структура для Int128, так что тебе не нужно байты перекладывать.
6.
public BigInteger (ReadOnlySpan<byte> value, bool isUnsigned = false, bool isBigEndian = false);
принимает байты от длинного целого. Так что у тебя твой
ToBigInteger
работает неправильно, если ты в него подаёшь указатель, на __int128
ptr_fact должно выглядеть как-то так:
void ptr_fact(int32_t n, __int128* result)
{
*result = fact(n);
}
[DllImport("Test")] static extern void ptr_fact(int n, out Int128 result);
Но смысла использовать ptr_fact я не вижу, тк обычный fact ты тоже легко можешь вызывать