从double数组转换为指针

Gra*_*ton 6 c# interop

我有这样的课

public unsafe class EigenSolver
{
   public double* aPtr
   {get; private set;}
   public EigenSolver(double* ap)
   {
      aPtr = ap;
   }
   public EigenSolver(double[] aa)
   {
     // how to convert from aa double array to pointer?
   }

   public void Solve()
   {
     Interop.CallFortranCode(aPtr);
   }
}
Run Code Online (Sandbox Code Playgroud)

你可以猜到,我需要从double数组转换为指针.怎么做?

注意:互操作功能 Interop.CallFortranCode(double* dPtr)是我无法改变的.

注意2:两个构造函数都是必需的,因为我的一些API用户希望传入指针,有些人希望传入数组.我不能强迫他们选择.

And*_*rew 9

使用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不会尝试在调用之外使用指针.一旦fixed语句超出范围,指针就不再有效了......

更新:

您无法获取参数的地址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));
   }
}

希望这有效......

安德鲁