2017-01-23 3 views
1

Ich versuche, eine Fortran-DLL dynamisch zu laden und übergeben Sie eine Zeichenfolge zurück von Fortran zu C#. Im Fortran-Code sieht alles gut aus, aber bei der Rückkehr zu C# ist der Wert der Zeichenfolge verloren. Stattdessen ist der Anfangswert, der in C# festgelegt wurde, zurück. Ich habe versucht, das Ref-Schlüsselwort zu verwenden, um die Zeichenfolge zu erhalten, die durch Verweis übergeben wird, aber dann erhalte ich Fehler wie unten. Was mache ich falsch?Zeichenfolge von Fortran dll an C übergeben #

Die Laufzeit hat einen schwerwiegenden Fehler festgestellt. Die Adresse des Fehlers war 0x709ce248 auf Thread 0x2ac4. Der Fehlercode lautet 0xc0000005. Dieser Fehler kann ein Fehler in der CLR oder in den unsicheren oder nicht verifizierbaren Teilen des Benutzercodes sein. Häufige Ursachen für diesen Fehler sind Benutzer-Marshalling-Fehler für COM-Interop oder PInvoke, die den Stack beschädigen können.

Fortran-Code:

module FortLibInterface 
implicit none 

integer, parameter :: STR_LENGTH = 256 

contains 

subroutine GetString(Str) 
    !DIR$ ATTRIBUTES DLLEXPORT::GetString 
    !DIR$ ATTRIBUTES ALIAS: 'GetString' :: GetString 
    !DIR$ ATTRIBUTES REFERENCE:: Str 

    character(len=STR_LENGTH), intent(inout) :: Str 

    Str = 'bcdef...' 

end subroutine 

end module 

C# -Code:

using System; 
using System.Runtime.InteropServices; 

namespace FortranCSTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string dllPath = "C:\\Temp\\FortLib.dll"; 

      FortLibTest lib = new FortLibTest(dllPath); 

      lib.MakeTestCall(); 
     } 
    } 

    public class FortLibTest 
    { 
     public const int STR_LENGTH = 256; 

     public const string FortranFuncName = "GetString"; 

     private string pathToDll = null; 

     [DllImport("kernel32.dll", SetLastError = true)] 
     private static extern IntPtr LoadLibrary(String DllName); 

     [DllImport("kernel32.dll")] 
     private static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName); 

     [DllImport("kernel32.dll")] 
     private static extern bool FreeLibrary(IntPtr hModule); 

     public FortLibTest(string FullPathToDll) 
     { 
      pathToDll = FullPathToDll; 
     } 

     [UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
     private delegate void TypeGetStrInfo(char[] str); 

     void GetStrInfo(char[] str) 
     { 
      IntPtr pDll = LoadLibrary(pathToDll); 
      if (pDll != IntPtr.Zero) 
      { 
       IntPtr pFunc = GetProcAddress(pDll, FortranFuncName); 
       if (pFunc != IntPtr.Zero) 
       { 
        TypeGetStrInfo func = (TypeGetStrInfo)Marshal.GetDelegateForFunctionPointer(pFunc, typeof(TypeGetStrInfo)); 

        func(str); 
       } 
       else 
       { 
        //Something 
       } 

       FreeLibrary(pDll); 
      } 
      else 
      { 
       //Something 
      } 
     } 

     public void MakeTestCall() 
     { 
      char[] str = new char[STR_LENGTH]; 

      str[0] = 'a'; 

      GetStrInfo(str); 
     } 
    } 
} 
+0

Funktioniert es, wenn Sie direkt '[DllImport (" FortLib.dll ")]'? – ja72

+0

Ja, es funktioniert. Das Problem ist, dass ich es dynamisch laden muss. – JesperW

+0

Nun, eigentlich. Es funktioniert, weil ich dann [in, out] hinzufügen kann. Wenn ich das hinterlasse, bekomme ich das gleiche Verhalten wie beim dynamischen Aufruf. – JesperW

Antwort

0

für die Zukunft. Ich habe [In, Out] hinzugefügt und alles funktioniert.

[DllImport(_dllName, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)] 
public static extern void GetString([In, Out] char[] str); 
Verwandte Themen