title: accessing pointer to fortran vector of doubles from multiple locations of C# program
body: <p>I'm working with a C# program that makes calls to a fortran DLL.  The example below shows some working C# code that declares a pointer of type double (&quot;ptr_spf&quot;), initializes it to null, and then passes it into fortran where it is filled (in this case, ptr_spf is pointing to a vector of doubles).  I am then able to loop over the fortran vector of doubles and add each entry to a C# list.  So far so good.</p>
  <p>Unfortunately as I've continued to develop the code, I'm realizing that what I've done so far is not sufficient.  Instead, I need to access the contents of ptr_spf from elsewhere in the C# code (different classes).  That is, instead of accessing the statically stored values contained within <code>SPFLowValues</code> List, I instead want to work with the updated values being pointed-to by ptr_spf because they are updated  by other calls to the fortran DLL.  My question is this: How do I declare ptr_spf at the top of the class and make it publicly available to other classes within the C# program?  When I attempted to move the declaration of ptr_spf to the top of the class, and define it with <code>public unsafe double* ptr_spf;</code>, Visual Studio doesn't like the fact that it is uninitialized when I go to use it (see the screen grab at the end of this post).  Bottom line, is there a way to make a pointer to a vector of fortran doubles publicly available so that I can access it from other parts of the C# program?</p>
  <p><strong>C#</strong>:</p>
  <pre><code>class cshare_call2fortran {
      // declaration of some variables
      public static List&lt;double&gt; SPFlowValues = new List&lt;double&gt;();
      ...
  
      // declare comms with fortran DLL
      ...
      [DllImport(&quot;libmf6d.dll&quot;, CallingConvention = CallingConvention.StdCall)]
      public unsafe static extern int get_value_ptr_double([In] byte[] address,
                                 [In, Out] ref double* ptr);
      ...
  
      // various functions
      ...
      // question pertains to the following function
      public static void get_spflow_ptr()
      {
          int index_spf = individual_varnames.FindIndex(x =&gt; x.Contains(&quot;INFLOW&quot;));
          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);
          unsafe
          {
              double* ptr_spf = null;
              result = get_value_ptr_double(SPFlow_Address, ref ptr_spf);
              for (int i = 0; i &lt; shape_spf[0]; ++i)
              {
                  SPFlowValues.Add(ptr_spf[i]);
                  spflow_len++;
              }
          }
      }
  }
  </code></pre>
  <p><strong>Fortran</strong> function (included in case it is helpful to see what's going on inside &quot;get_value_ptr_double&quot;):</p>
  <pre><code>function get_value_ptr_double(c_var_address, c_arr_ptr) result(bmi_status) bind(C, name=&quot;get_value_ptr_double&quot;)
  !DEC$ ATTRIBUTES DLLEXPORT :: get_value_ptr_double
    character (kind=c_char), intent(in) :: c_var_address(*) !&lt; memory address string of the variable
    type(c_ptr), intent(inout) :: c_arr_ptr                 !&lt; pointer to the array
    integer(kind=c_int) :: bmi_status                       !&lt; BMI status code
    ! local
    character(len=LENMEMPATH) :: mem_path
    character(len=LENVARNAME) :: var_name
    integer(I4B) :: access_type
    logical(LGP) :: found
    real(DP), pointer :: scalar_ptr
    real(DP), dimension(:), pointer, contiguous :: array_ptr
    real(DP), dimension(:,:), pointer, contiguous :: array2D_ptr
    integer(I4B) :: rank    
    
    bmi_status = BMI_FAILURE
  
    call split_address(c_var_address, mem_path, var_name)
    
    rank = -1
    call get_mem_rank(var_name, mem_path, rank)
    if (rank == 0) then
      call mem_setptr(scalar_ptr, var_name, mem_path)
      c_arr_ptr = c_loc(scalar_ptr)
    else if (rank == 1) then
      call mem_setptr(array_ptr, var_name, mem_path)
      c_arr_ptr = c_loc(array_ptr)
    else if (rank == 2) then
      call mem_setptr(array2D_ptr, var_name, mem_path)
      c_arr_ptr = c_loc(array2D_ptr)
    else
      write(istdout,*) 'BMI Error: unsupported rank for variable '//var_name
      return
    end if
  
    bmi_status = BMI_SUCCESS    
    
  end function get_value_ptr_double
  </code></pre>
  <p>The following is a screen grab showing the error when attempting to move the declaration of ptr_spf to the beginning of the class:
  <a href="https://i.stack.imgur.com/FMBgB.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/FMBgB.png" alt="enter image description here" /></a></p>