Я пытаюсь обернуть некоторый устаревший код C для использования с C#, работающим на .NET Core. Я использую приведенный здесь подход для создания оболочки C++, которая компилируется в чистый MSIL. Это хорошо работает для простых функций, но я обнаружил, что если мой код когда-либо использует указатели на указатели или массивы указателей, он рухнет с нарушением памяти. Часто вылетает Visual Studio и приходится все перезагружать, что утомительно.
Например, следующий код вызовет сбои:
public ref class example
{
public:
static void test() {
Console::WriteLine("\nTesting pointers.");
double a[5] = {5,6,7,8,9}; //Array.
double *b = a; //Pointer to first element in array.
Console::WriteLine("\nTesting bare pointers.");
Console::WriteLine(a[0]); //Prints 5.
Console::WriteLine(b[0]); //Prints 5.
Console::WriteLine("\nTesting pointer-to-pointer.");
double **c = &b;
Console::WriteLine(c == &b); //Prints true.
Console::WriteLine(b[0]); //Works, prints 5.
Console::WriteLine(**c); //Crashes with memory access violation.
Console::WriteLine("\nTesting array of pointers.");
double* d[1];
d[0] = b;
Console::WriteLine(d[0] == b); //Prints false???
Console::WriteLine(b[0]); //Works, prints 5.
Console::WriteLine(d[0][0]); //Crashes with memory access violation.
Console::WriteLine("\nTesting CLI array of pointers.");
cli::array<double*> ^e = gcnew cli::array<double*> (5);
e[0] = b;
Console::WriteLine(e[0] == b); //Prints false???
Console::WriteLine(b[0]); //Works, prints 5.
Console::WriteLine(e[0][0]); //Crashes with memory access violation.
}
}
Обратите внимание, что простое использование указателей не вызывает никаких проблем. Это только тогда, когда есть дополнительный уровень косвенности.
Если я добавляю код в консольное приложение CLR C++, оно работает точно так, как ожидалось, и не дает сбоев. Сбой происходит только при компиляции кода в сборку MSIL с clr:pure
и запуске из основного приложения .NET.
Что может происходить?
Обновление 1. Вот файлы Visual Studio: https://app.box.com/s/xejfm4s46r9hs0inted2kzhkh9qzmjpb Это два проекта. Сборка MSIL называется library
, а CoreApp
— это консольное приложение C#, которое вызывает библиотеку. Предупреждение, при запуске Visual Studio может произойти сбой.
Обновление 2: я тоже это заметил:
double a[5] = { 5,6,7,8,9 };
double* d[1];
d[0] = a;
Console::WriteLine(d[0] == a); //Prints true.
Console::WriteLine(IntPtr(a)); //Prints a number.
Console::WriteLine(IntPtr(d[0])); //Prints a completely different number.