title: Type marshalling to call a fortran subroutine from C#
body: <p>I'm trying to call a FORTRAN77 subroutine from C# code using P/invoke - in case you're interested, I'm trying to wrap some of the functionality offered by the ARPACK library (<a href="http://www.caam.rice.edu/software/ARPACK/" rel="nofollow noreferrer">http://www.caam.rice.edu/software/ARPACK</a>). I have 2 questions.</p>
  
  <hr>
  
  <p>First off, I couldn't find clear instructions anywhere regarding type marshalling in this context. More specifically, here are the types that are declared in my FORTRAN subroutine:</p>
  
  <pre><code>       subroutine getEigenVectors
        &amp;   ( Matrix, n, which, nev, ncv, maxn, maxnev, maxncv, ldv, v, d)
  
   c     %------------------%
   c     | Scalar Arguments |
   c     %------------------%
  
         character        which*2
         integer          n, nev, maxn, maxnev, maxncv, ldv
  
   c     %-----------------%
   c     | Array Arguments |
   c     %-----------------%
   c
         Real           
        &amp;                 Matrix(n,n), v(ldv,maxncv), d(maxncv,2)
  </code></pre>
  
  <p>I found some valuable info here: 
  <a href="https://stackoverflow.com/questions/2376585/what-should-i-marshalas-for-character-type-in-fortran">What Should I MarshalAs for Character Type in Fortran?</a>, from which I implied (I might be wrong) that I should use:</p>
  
  <ul>
  <li><code>[MarshalAs(UnmanagedType.I4)] int</code> to pass in integers</li>
  <li><code>[MarshalAs(UnmanagedType.LPArray)] byte[]</code> to pass in character strings</li>
  </ul>
  
  <p>However, I have absolutely no idea what to do with the <code>Real</code> arrays. <strong>Does anyone have any idea on that?</strong></p>
  
  <hr>
  
  <p>Secondly, I am confused as to whether I should pass my arguments as reference or not. I am by no means familiar with FORTRAN - I know, that makes the task a little difficult; however, only ARPACK does what I would like to do.I did read somewhere though that FORTRAN subroutines take all their arguments as reference by default. <strong>Should I therefore pass all arguments as references?</strong></p>
  
  <p>Thanks in advance for your help!
  Guillaume</p>
  
  <hr>
  
  <p><strong>EDIT</strong> (8/6/11)</p>
  
  <p>So here's my final take:</p>
  
  <pre><code>    [DllImport("Arpack.dll", EntryPoint = "#140")]
      private static extern void getEigenVectors(
          [MarshalAs(UnmanagedType.LPArray)] ref float[,] matrix, 
          [MarshalAs(UnmanagedType.I4)] ref int n,
          [MarshalAs(UnmanagedType.LPArray)] ref byte[] which,
          [MarshalAs(UnmanagedType.I4)] int whichLength,
          [MarshalAs(UnmanagedType.I4)] ref int nev, 
          [MarshalAs(UnmanagedType.I4)] ref int ncv,
          [MarshalAs(UnmanagedType.I4)] ref int maxn,
          [MarshalAs(UnmanagedType.I4)] ref int maxnev,
          [MarshalAs(UnmanagedType.I4)] ref int maxncv,
          [MarshalAs(UnmanagedType.I4)] ref int ldv,
          [MarshalAs(UnmanagedType.LPArray)] ref float[,] v,
          [MarshalAs(UnmanagedType.LPArray)] ref float[,] d
      );
  </code></pre>
  
  <p>Several things I did here: </p>
  
  <ul>
  <li>Pass <code>int</code> objects marshalled as <code>UnmanagedType.I4</code> to match FORTRAN <code>integer</code> objects</li>
  <li>Pass <code>float[,]</code> objects of size (m, n) and marshalled as <code>UnmanagedType.LPArray</code> to match FORTRAN <code>Real(n,m)</code> objects</li>
  <li><p>Pass <code>byte[]</code> objects obtained marshalled as <code>UnmanagedType.LPArray</code> to match FORTRAN <code>Character*n</code> objects. The <code>byte[]</code> objects are computed as follows: </p>
  
  <pre><code>System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding();
  byte[] which = encoding.GetBytes(myString);
  </code></pre></li>
  <li>Pass an <code>int</code> object BY VALUE and marshalled as <code>UnmanagedType.I4</code> to indicate the length of the string. Note that I tried to put that argument right after the string as well as at the end of the arguments list.</li>
  </ul>
  
  <p>This is my best shot - neither this nor all the other things I tried worked. The method will execute, however it exits super fast (when it's supposed to be doing some pretty severe computations). Moreover, my 3 arrays are transformed into weird uni-dimensional arrays. Here what the debugger gives me:</p>
  
  <p><img src="https://i.stack.imgur.com/hM1Q1.png" alt="enter image description here"></p>
  
  <p>Any idea?</p>