DLL-Methoden hinzufügen (.NET 2 FORTRAN)
Jump to navigation
Jump to search
Anleitung für das Hinzufügen neuer Methoden in eine Modell-DLL (am Beispiel von BlueM.Sim)
Hinzufügen der neuen Methode in der BlueM.Sim Fortran-DLL
1 2 3 4 5 | logical function GetModelDescription ( Description ) !DEC$ ATTRIBUTES DLLEXPORT :: GETMODELDESCRIPTION character ( * ) Description ... end function |
- Funktionsname und DLLEXPORT-Name müssen gleich sein !
- Übergabeparameter müssen definiert sein (und die Typen sollten so einfach wie möglich sein) !
- Tip
- Kontrollieren, ob der Export funktioniert hat, kann man mit dem DependencyWalker des Visual Studios
C:\Programme\Microsoft Visual Studio 8\Common7\Tools\Bin\Depends.Exe
.
Dort werden alle exportierte Methoden aufgelistet.
Erweiterung des DLL-Wrappers (C#)
Die Methoden der DLL werden aus der Klasse DLLMethoden
aufgerufen.
- Hinzufügen des Delegats in DLLMethoden
- Hinzufügen der Schnittstellenmethode
- Hinzufügen einer Testmethode (siehe UnitTest)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | public class DLLMethoden { ... delegate bool GetModelDescriptionDelegate([MarshalAs(UnmanagedType.LPStr)] StringBuilder description, uint length); ... public bool GetModelDescription(StringBuilder description, uint length) { if (myDll == IntPtr.Zero) InitializeMyDll(pathToDll); IntPtr pProc = DllImportDynamic.GetProcAddress(myDll, "OPENMI_mp_GETMODELDESCRIPTION" ); GetModelDescriptionDelegate cpv = (GetModelDescriptionDelegate)Marshal.GetDelegateForFunctionPointer(pProc, typeof (GetModelDescriptionDelegate)); return cpv(description, ( uint )description.Length); } ... } |
Delegate
Eine Delegatmethode ist eine Art "Platzhalter". in diesem Beispiel fungiert sie als Platzhalter für die Fortran-DLL. Sie hat die selben Übergabeparameter wie in der Fortran-DLL beschrieben - Ausnahme sind Zeichenketten (Siehe Marshaling).
Marshaling
- Um Typensicherheit zu gewährleiseten, gibt es in .NET die Attributsklasse
MarshalAs
. Über diese Klasse können Typen aus unmanaged Code und dem .NET Code ausgetauscht werden - z.B.r8
unddouble
oder wie beiGetModelDescriptionDelegate
eine Zeichenkette (LPStr
/StringBuilder
):
1 | [MarshalAs(UnmanagedType.LPStr)] StringBuilder description |
- Um eine Zeichenkette mit der Fortran-DLL auszutauschen, muss zu dem inhalt immer auch die Länge des Strings angegeben werden:
1 | uint length |
Aufruf der DLL-Methode
1 | IntPtr pProc = DllImportDynamic.GetProcAddress(myDll, "OPENMI_mp_GETMODELDESCRIPTION" ); |
Holt sich die Einsprungadresse der DLL_Methode.
1 | GetModelDescriptionDelegate cpv = (GetModelDescriptionDelegate)Marshal.GetDelegateForFunctionPointer(pProc, typeof (GetModelDescriptionDelegate)); |
Die Einsprungadresse und der "Platzhalter" werden miteinander verknüpft. Nun kann man einfach die Delegatmethode mit den entsprechenden Parametern aufrufen:
1 | cpv(description, ( uint )description.Length); |