我有这样的课
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用户希望传入指针,有些人希望传入数组.我不能强迫他们选择.
使用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));
}
}
希望这有效......
安德鲁
| 归档时间: |
|
| 查看次数: |
7281 次 |
| 最近记录: |