C#调用Fortran DLL时如何实现跨类公开访问的double指针并避免未初始化报错
报错翻译
你遇到的类顶层指针未初始化的英文报错,对应中文含义如下:
- 若为静态方法访问非静态字段触发的报错:
CS0120: 需要对非静态字段、方法或属性“cshare_call2fortran.ptr_spf”的对象引用 - 若为指针未赋值触发的使用错误:
CS0165: 使用了未赋值的变量“ptr_spf”
解决步骤
- 项目前置配置:打开项目属性 → 生成选项卡,勾选允许不安全代码,否则C#不支持声明非托管指针类型。
- 类字段调整:在
cshare_call2fortran类顶层声明静态、显式初始化的指针字段,替代原局部变量逻辑:
class cshare_call2fortran { // 原有静态List可按需保留做备份,不需要可直接删除 public static List<double> SPFlowValues = new List<double>(); // 公开静态指针,显式初始化为null避免未初始化报错 public unsafe static double* ptr_spf = null; // 缓存数组长度,避免重复查询Fortran端形状 public static int spflow_len = 0; // 其余原有DllImport声明、工具方法逻辑保持不变 // ... }
- 修改
get_spflow_ptr方法,直接给类级指针赋值:
public static void get_spflow_ptr() { int index_spf = individual_varnames.FindIndex(x => x.Contains("INFLOW")); var SPFlow_Address = Encoding.ASCII.GetBytes(individual_varnames[index_spf] + char.MinValue); int rank_spf = 0; result = get_var_rank(SPFlow_Address, ref rank_spf); var shape_spf = new int[rank_spf]; result = get_var_shape(SPFlow_Address, shape_spf); spflow_len = shape_spf[0]; // 缓存数组长度 unsafe { // 直接给类级ptr_spf赋值,不再声明局部指针变量 result = get_value_ptr_double(SPFlow_Address, ref ptr_spf); // 可选:需要缓存旧值时保留以下遍历逻辑 // for (int i = 0; i < spflow_len; ++i) // { // SPFlowValues.Add(ptr_spf[i]); // } } }
实时访问方法
其他类需要获取Fortran端实时更新的数值时,直接通过cshare_call2fortran.ptr_spf[i]读取即可。该指针直接指向Fortran端管理的内存区域,只要Fortran端未释放该块内存、未改变对应变量的指向,读取到的就是最新的数值,无需重新拷贝。
注意事项
- 必须先成功执行
get_spflow_ptr完成指针初始化后,再跨类访问该指针,否则指针为null会触发非法内存访问异常。 - 该指针指向的内存完全由Fortran DLL管理,禁止在C#侧手动释放、修改该内存块的地址属性,避免Fortran端运行崩溃。
- 读取数组元素前建议通过缓存的
spflow_len校验索引合法性,避免越界访问。
内容的提问来源于stack exchange,提问作者user2256085
相关产品推荐
相关产品推荐

