Frage

Ich versuche, zu einem Legacy-DLL von Fortran-Code kompiliert zu rufen. Ich bin neu in Interop, aber ich habe einige Artikel über sie gelesen und es scheint, wie mein Fall recht einfach sein sollte.

Die Methode, die ich wirklich nennen will eine komplexe Methode Unterschrift, aber ich kann diese einfache GetVersion Methode nicht einmal aufrufe, ohne eine geschützte Speicherverletzung zu bekommen.

Hier ist mein DllImport Code:

[DllImport("GeoConvert.dll", 
            EntryPoint="_get_version@4", 
            CallingConvention=CallingConvention.StdCall)]
public static extern void GetGeoConvertVersion([MarshalAs(UnmanagedType.LPStr, SizeConst=8)]
                                                    ref string version);

Hier ist der Fortran-Code:

SUBROUTINE GetVer( VRSION )
C
!MS$DEFINE  MSDLL 
!MS$IF DEFINED (MSDLL)
        ENTRY Get_Version (VRSION)  
      !MS$ATTRIBUTES DLLEXPORT,STDCALL :: Get_Version
      !MS$ATTRIBUTES REFERENCE :: VRSION
!MS$ENDIF
!MS$UNDEFINE  MSDLL 
C
  CHARACTER*8  VRSION
C
  VRSION = '1.0a_FhC'                                        
C
  RETURN
  END

Hier ist meine Unit-Test, der fehlschlägt:

[Test]
public void TestGetVersion()
{
    string version = "";
    LatLonUtils.GetGeoConvertVersion(ref version);
    StringAssert.IsNonEmpty(version);
}

Hier ist die Fehlermeldung erhalte ich:

System.AccessViolationException
Message: Attempted to read or write protected memory. 
         This is often an indication that other memory is corrupt.

Andere Dinge, die ich versucht habe:

  • Verwenden der Standard-Rangier
  • ein char Passing [] anstelle eines Strings (Methodensignatur Fehler stattdessen erhalten)
War es hilfreich?

Lösung 2

OK, habe ich es zu arbeiten, das Problem durch ref vorging. Ich bin mir nicht sicher, warum, aber das funktioniert:

[DllImport("GeoConvert.dll", 
                EntryPoint="_get_version@4", 
                CallingConvention=CallingConvention.StdCall)]
    public static extern void GetGeoConvertVersion([MarshalAs(UnmanagedType.LPArray)]
                                                    byte[] version);

Mit diesem Test:

[Test]
    public void TestGetVersion()
    {
        //string version = "";
        byte[] version = new byte[8];
        LatLonUtils.GetGeoConvertVersion(version);
        char[] versionChars = System.Text.Encoding.ASCII.GetChars(version);

        string versionString = new string(versionChars);
    }

Andere Tipps

... schnipp ... OK, ich habe es zu arbeiten, das Problem durch ref vorging. Ich bin mir nicht sicher, warum, aber das funktioniert: ... schnipp ...

Sie müssen durch Verweis übergeben, weil das die semantischen Wesen durch den Fortran-Code verwendet wird. Der Client-Code wird in einem Puffer übergeben, die die Fortran-Code auf der Verwendung eines Rückgabewert statt schreiben wird.

... schnipp ... ! MS $ attributes BEZUG :: vrsion ... schnipp ...

Dieses Attribut in Ihrem Fortran-Code gibt an, dass dieser Parameter als Referenz übergeben wird. Das heißt, der Fortran-Code an diese Adresse schreiben wird. Wenn der DllImport erklärt nicht, es als Sollwert auch, erhalten Sie eine Zugriffsverletzung erhalten.

Haben Sie versucht, einen Stringbuilder verwenden?

Erstellen Sie Ihren String als String und passiert, dass in die DLL-Funktion.

Im nicht sicher, was Marashlling Anweisung zu verwenden, perhapse der Standard funktionieren könnte.

Haben Sie einen Blick unter: Marshal C ++ „string“ Klasse in C # P / Invoke

Hier ist ein guter Artikel das könnte auch helfen: Interop Rangierung

Ich kann diese Lösung nicht versuchen, da ich keine Fortran-Compiler, aber ich denke, das ist für Sie arbeiten würde:

    [DllImport("GeoConvert.dll", 
            EntryPoint="_get_version@4", 
            CallingConvention=CallingConvention.StdCall,
            CharSet=CharSet.Ansi)]
    public static extern void GetGeoConvertVersion(StringBuilder version);

Danke alle Jungs, ich habe eine Reihe von c # zu einem Unterprogramm von Fortran-DLL und diese Methode zu übergeben versuche, war die einzige Arbeit eines unter vielen anderen

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top