Используйте оператор fixed
:
fixed (double* aaPtr = aa) {
// You can use the pointer in here.
}
Хотя в контексте fixed
память для вашей переменной закреплена, поэтому сборщик мусора не будет пытаться переместить ее.
Я бы взял этот подход вместо:
public class EigenSolver
{
public double[] _aa;
/*
There really is no reason to allow callers to pass a pointer here,
just make them pass the array.
public EigenSolver(double* ap)
{
aPtr = ap;
}
*/
public EigenSolver(double[] aa)
{
_aa = aa;
}
public void Solve()
{
unsafe {
fixed (double* ptr = _aa) {
Interop.CallFortranCode(ptr);
}
}
}
}
Это предполагает, конечно, что CallFortranCode не пытается использовать указатель вне вызова. Когда фиксированный оператор выходит из области видимости, указатель становится недействительным ...
UPDATE:
Невозможно взять адрес аргумента double[] aa
и сохранить его в поле вашего экземпляра. Даже если компилятор разрешит вам, GC будет перемещать эту память, оставляя ваш указатель бесполезным.
Возможно, вы могли бы сделать это: Используйте Marshal.AllocHGlobal, чтобы выделить достаточно памяти для хранения всех элементов массива (aa.Length * sizeof(double))
). Затем используйте Marshal.Copy, чтобы скопировать содержимое массива в недавно выделенную память:
bool _ownsPointer;
public EigenSolver(double[] aa) {
IntPtr arrayStore = (double*)Marshal.AllocHGlobal(aa.Length * sizeof(double));
Marshal.Copy(aa, 0, arrayStore, aa.Length);
this.aPtr = (double*)arrayStore.ToPointer();
_ownsPointer = true;
}
~EigenSolver {
if (_ownsPointer) {
Marshal.FreeHGlobal(new IntPtr(this.aPtr));
}
}
Надеюсь, это работает ...
Andrew