DLL-Methoden hinzufügen: Difference between revisions
m (→Delegate) |
m (Formatierung) |
||
Line 1: | Line 1: | ||
= | <div style="float:left; margin-right:10px">__TOC__</div> | ||
<big> Anleitung für das Hinzufügen neuer Methoden in eine Modell-DLL (am Beispiel von [[BlueM]]) </big><br clear="all"/> | |||
== Hinzufügen der neuen Methode in der BlueM Fortran-DLL == | |||
<fortran> | <fortran> | ||
Line 14: | Line 15: | ||
; Tip : Kontrollieren, ob der Export funktioniert hat, kann man mit dem DependencyWalker des Visual Studios | ; Tip : Kontrollieren, ob der Export funktioniert hat, kann man mit dem DependencyWalker des Visual Studios <br/><code>C:\Programme\Microsoft Visual Studio 8\Common7\Tools\Bin\Depends.Exe</code>. <br/>Dort werden alle exportierte Methoden aufgelistet. | ||
== Erweiterung des [[BlueM.DLLAdapter|DLL-Wrappers]] (C#) == | |||
Die Methoden der DLL werden aus der Klasse <code>DLLMethoden</code> aufgerufen. | Die Methoden der DLL werden aus der Klasse <code>DLLMethoden</code> aufgerufen. | ||
Line 43: | Line 44: | ||
</csharp> | </csharp> | ||
==== 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]]). | 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]]). | ||
==== 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. <code>r8</code> und <code>double</code> oder wie bei <code>GetModelDescriptionDelegate</code> eine Zeichenkette (<code>LPStr</code>/<code>StringBuilder</code>): | * 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. <code>r8</code> und <code>double</code> oder wie bei <code>GetModelDescriptionDelegate</code> eine Zeichenkette (<code>LPStr</code>/<code>StringBuilder</code>): | ||
<csharp> [MarshalAs(UnmanagedType.LPStr)] StringBuilder description </csharp> | <csharp> [MarshalAs(UnmanagedType.LPStr)] StringBuilder description </csharp> | ||
Line 52: | Line 53: | ||
<csharp> uint length </csharp> | <csharp> uint length </csharp> | ||
==== Aufruf der DLL-Methode ==== | |||
<csharp>IntPtr pProc = DllImportDynamic.GetProcAddress(myDll, "OPENMI_mp_GETMODELDESCRIPTION");</csharp> | <csharp>IntPtr pProc = DllImportDynamic.GetProcAddress(myDll, "OPENMI_mp_GETMODELDESCRIPTION");</csharp> | ||
Holt sich die Einsprungadresse der DLL_Methode. | Holt sich die Einsprungadresse der DLL_Methode. |
Revision as of 02:28, 2 November 2007
Anleitung für das Hinzufügen neuer Methoden in eine Modell-DLL (am Beispiel von BlueM)
Hinzufügen der neuen Methode in der BlueM Fortran-DLL
<fortran>
logical function GetModelDescription(Description) !DEC$ ATTRIBUTES DLLEXPORT :: GETMODELDESCRIPTION character(*) Description ... end function
</fortran>
- 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 UnitTest
<csharp>
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); } ... }
</csharp>
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
):
<csharp> [MarshalAs(UnmanagedType.LPStr)] StringBuilder description </csharp>
- Um eine Zeichenkette mit der Fortran-DLL auszutauschen, muss zu dem inhalt immer auch die Länge des Strings angegeben werden:
<csharp> uint length </csharp>
Aufruf der DLL-Methode
<csharp>IntPtr pProc = DllImportDynamic.GetProcAddress(myDll, "OPENMI_mp_GETMODELDESCRIPTION");</csharp> Holt sich die Einsprungadresse der DLL_Methode. <csharp>GetModelDescriptionDelegate cpv = (GetModelDescriptionDelegate)Marshal.GetDelegateForFunctionPointer(pProc, typeof(GetModelDescriptionDelegate));</csharp> Die Einsprungadresse und der "Platzhalter" werden miteinander verknüpft. Nun kann man einfach die Delegatmethode mit den entsprechenden Parametern aufrufen: <csharp>cpv(description, (uint)description.Length);</csharp>