Präsentation herunterladen
Die Präsentation wird geladen. Bitte warten
Veröffentlicht von:Werther Gerstel Geändert vor über 11 Jahren
1
Migration und Nutzung von vorhandenem Code Interoperability
2
Bernd Marquardt Software & Consulting berndm@go-sky.de
3
Agenda Das Problem des alten Codes Das Problem des alten Codes Einführung Einführung Interop-Möglichkeiten Interop-Möglichkeiten DLLs DLLs COM COM ActiveX ActiveX Wrapper-Klassen Wrapper-Klassen Unmanaged Code ruft managed Code auf Unmanaged Code ruft managed Code auf Migration Migration Zusammenfassung Zusammenfassung
4
Einführung Grundsätzlich gibt es im Moment in der Windows-Welt zwei Arten von Code: Grundsätzlich gibt es im Moment in der Windows-Welt zwei Arten von Code: Unmanaged Code (Die alte Welt) Unmanaged Code (Die alte Welt) Alter x86-Maschinencode Alter x86-Maschinencode Wird sofort ausgeführt Wird sofort ausgeführt Managed Code (Die.NET-Welt) Managed Code (Die.NET-Welt) Neuer, maschinenunabhängiger IL- Code Neuer, maschinenunabhängiger IL- Code Wird zur Laufzeit in Maschinencode übersetzt und ausgeführt Wird zur Laufzeit in Maschinencode übersetzt und ausgeführt
5
Einführung In beiden Welten gibt es unterschiedliche Codesorten: In beiden Welten gibt es unterschiedliche Codesorten: Unmanaged: Clients (EXE), DLLs mit APIs, COM-Komponenten (als DLL und als EXE), ActiveX-Komponenten, normale Klassenbibliotheken Unmanaged: Clients (EXE), DLLs mit APIs, COM-Komponenten (als DLL und als EXE), ActiveX-Komponenten, normale Klassenbibliotheken Managed: Clients (EXE),.NET- Komponenten Managed: Clients (EXE),.NET- Komponenten
6
Einführung In den Code der alten Welt wurde sehr viel Geld investiert In den Code der alten Welt wurde sehr viel Geld investiert Es ist unmöglich, in kurzen Zeit alles wieder neu für.NET zu programmieren Es ist unmöglich, in kurzen Zeit alles wieder neu für.NET zu programmieren Welche Möglichkeiten gibt es in.NET, mit altem Code weiterzuarbeiten? Welche Möglichkeiten gibt es in.NET, mit altem Code weiterzuarbeiten?
7
Einführung Was macht die gemeinsame Nutzung von.NET und unman. Code schwer? Was macht die gemeinsame Nutzung von.NET und unman. Code schwer? Monolithischer Code (eine EXE) Monolithischer Code (eine EXE) Was macht die gemeinsame Nutzung von.NET und unman. Code leicht? Was macht die gemeinsame Nutzung von.NET und unman. Code leicht? Aufteilung des gesamten Projektes in kleine Einheiten (Client, DLLs, COM- und ActiveX-Komponenten) Aufteilung des gesamten Projektes in kleine Einheiten (Client, DLLs, COM- und ActiveX-Komponenten)
8
DLL (API) aus man. Code Unmanaged DLLs mit Attribut DllImport Unmanaged DLLs mit Attribut DllImport [DllImport (Kernel32.Dll)] public extern static void Sleep(uint uiMSec); [DllImport (Kernel32.Dll, EntryPoint = Sleep)] public extern static void Schlaf(uint uiMSec); [DllImport (User32.Dll, CharSet = CharSet::Ansi)] public extern static void MessageBox(int hWnd, string strMsg, string strTitel, uint uiFlags);
9
Beispiel für Standard-Marshaller int SomeFunc(int sel, void* buf, int size); [DllImport("some.dll")] static extern int SomeFunc(int sel, [MarshalAs(UnmanagedType.LPArray)] byte[] buf, int size); [DllImport("some.dll", EntryPoint="SomeFunc")] static extern int SomeFunc_String(int sel, StringBuilder sb, int size); [DllImport("some.dll", EntryPoint="SomeFunc")] static extern int SomeFunc_Int(int sel, ref int i, int size); Methode in einer Standard-DLL Methode in einer Standard-DLL Einfache Deklaration erfordert u.U. spezielle Dekodierung Einfache Deklaration erfordert u.U. spezielle Dekodierung Maßgeschneiderte Versionen möglich Maßgeschneiderte Versionen möglich
10
Array als Referenzparameter // Originaldeklaration der Library-Funktion // int f(int** ppArray, int* pSize); [DllImport("PInvokeLib.dll")] public static extern int f(ref IntPtr array, ref int size); // Unmanaged Speicherbereich anlegen IntPtr buffer = Marshal.AllocCoTaskMem( Marshal.SizeOf(size) * array2.Length); // Daten in Speicherbereich kopieren Marshal.Copy(array2, 0, buffer, array2.Length); int res = f(ref buffer, ref size); int[] arrayRes = new int[size]; // Daten zurückkopieren Marshal.Copy(buffer, arrayRes, 0, size); // Unmanaged Speicherbereich freigeben Marshal.FreeCoTaskMem(buffer);
11
DLL (API) aus man. Code System-DLLs und eigene DLLs können aufgerufen werden System-DLLs und eigene DLLs können aufgerufen werden Typ-Konvertierungen der Standardtypen werden automatisch gemacht Typ-Konvertierungen der Standardtypen werden automatisch gemacht Aufruf ist etwas langsamer, als aus unmanaged Code Aufruf ist etwas langsamer, als aus unmanaged Code Interfaces als Parameter werden unterstützt Interfaces als Parameter werden unterstützt Können nicht als Ausgabeparameter dienen Können nicht als Ausgabeparameter dienen Arrays von Basistypen können benutzt werden Arrays von Basistypen können benutzt werden Attribute steuern Konvertierung Attribute steuern Konvertierung
12
DllImport – wann nicht? Beispiel: char* DoSomething(...) Beispiel: char* DoSomething(...) [DllImport (TheSuperLib)] extern C String* DoSomething(...); Problem hier: Problem hier: Der Speicher, auf den der Zeiger zeigt, kann nicht freigegeben werden Der Speicher, auf den der Zeiger zeigt, kann nicht freigegeben werden
13
DLL (API) aus man. Code Zweite Methode: IJW = It just works Zweite Methode: IJW = It just works Geht nur mit managed C++ Extensions Geht nur mit managed C++ Extensions Benötigte C/C++-Header-Datei muss eingefügt werden Benötigte C/C++-Header-Datei muss eingefügt werden Z.B.: #include Z.B.: #include Aufruf der API-Funktionen ist jetzt möglich Aufruf der API-Funktionen ist jetzt möglich
14
DLL (API) aus man. Code Vorteile von IJW: Vorteile von IJW: Kein DllImport erforderlich Kein DllImport erforderlich Geringfügig schneller Geringfügig schneller Bei Aufruf mehrerer unmanaged APIs: Die Daten müssen nur einmal gemarshalled werden Bei Aufruf mehrerer unmanaged APIs: Die Daten müssen nur einmal gemarshalled werden
15
COM aus man. Code Erzeugung eines Runtime-Callable- Wrappers (RCW) durch.NET Erzeugung eines Runtime-Callable- Wrappers (RCW) durch.NET Unmanaged Code COM-Objekt Managed Code RuntimeCallableWrapper Managed Client
16
COM aus man. Code Wrapper von Hand erzeugen mit: Wrapper von Hand erzeugen mit: TblImp.EXE TblImp.EXE Wrapper automatisch erzeugen mit: Wrapper automatisch erzeugen mit: Visual Studio.NET Visual Studio.NET Befehl Add Reference Befehl Add Reference Ist in vielen Fällen ausreichend Ist in vielen Fällen ausreichend Datenkonvertierung findet statt Datenkonvertierung findet statt Z.B.: String nach BSTR Z.B.: String nach BSTR Geht nicht bei Custom Marshaling Geht nicht bei Custom Marshaling
17
COM aus man. Code Problem bei der Benutzung der COM- Komponenten: Problem bei der Benutzung der COM- Komponenten: Durch den Garbage Collector von.NET wird die COM-Komponente nicht sofort freigegeben Durch den Garbage Collector von.NET wird die COM-Komponente nicht sofort freigegeben Das kann zu unerwartetem Verhalten führen Das kann zu unerwartetem Verhalten führen Lösungen: Lösungen: Aufruf von System.GC.Collect (nicht gut!) Aufruf von System.GC.Collect (nicht gut!) Aufruf von System.Runtime.InteropServices.Marshal. ReleaseComObject Aufruf von System.Runtime.InteropServices.Marshal. ReleaseComObject
18
Rückgabewerte und Exceptions COM meldet Fehler via Result-Code zurück COM meldet Fehler via Result-Code zurück.NET-Methoden werfen Exceptions.NET-Methoden werfen Exceptions Runtime setzt Konzepte ineinander um Runtime setzt Konzepte ineinander um HRESULT gibt Fehlerklasse an HRESULT gibt Fehlerklasse an Zusätzliche Informationen werden via IErrorInfo erhalten Zusätzliche Informationen werden via IErrorInfo erhalten Ein COM-Objekt sollte dieses Interface implementieren Ein COM-Objekt sollte dieses Interface implementieren
19
Early und Late Binding Early Binding: Objekterzeugung mit new Early Binding: Objekterzeugung mit new Late Binding: (IDispatch) Late Binding: (IDispatch) Benutzung von Type.GetTypeFromProgID, Activator.CreateInstance und Type.InvokeMember Benutzung von Type.GetTypeFromProgID, Activator.CreateInstance und Type.InvokeMember Parameterübergabe in einem Array Parameterübergabe in einem Array
20
Aufruf eines COM-Servers (late) namespace LateBoundClient { using System.Reflection;... Type typ; Object obj; Object[] prms = new Object[2]; int r; using System.Reflection;... Type typ; Object obj; Object[] prms = new Object[2]; int r; typ = Type.GetTypeFromProgID(MyLib.MyServer"); obj = Activator.CreateInstance(typ); prms[0] = 10; prms[1] = 150; typ = Type.GetTypeFromProgID(MyLib.MyServer"); obj = Activator.CreateInstance(typ); prms[0] = 10; prms[1] = 150; r = (int)typ.InvokeMember(aMethod", BindingFlags.InvokeMethod, null, obj, prms);... r = (int)typ.InvokeMember(aMethod", BindingFlags.InvokeMethod, null, obj, prms);...}
21
Wrapper-Klassen Managed Wrapper-Klassen umhüllen eine normale unmanaged C++-Klasse Managed Wrapper-Klassen umhüllen eine normale unmanaged C++-Klasse Die Hüllklasse funktioniert wie ein Proxy Die Hüllklasse funktioniert wie ein Proxy Die Hüllklasse hat die gleiche Funktionalität wie die C++-Klasse Die Hüllklasse hat die gleiche Funktionalität wie die C++-Klasse Es wird immer ein Klassenpaar erzeugt, bzw. zerstört Es wird immer ein Klassenpaar erzeugt, bzw. zerstört
22
Wrapper-Klassen class CppClass { public: // Konstruktor CppClass() { …} // Destruktor ~CppClass() { …} // Methoden void native_f() { …} }; __gc class ManClass { public: // Konstruktor ManClass() { m_pC = new CppClass(); } // Freigabe ~ManClass() { delete m_pC; } // Methoden void managed_f() { m_pC->native_f(); } private: CppClass * m_pC; };
23
Wrapper-Klassen Erzeugung von Wrapper-Klassen Erzeugung von Wrapper-Klassen Erzeugung einer man. C++-Klasse Erzeugung einer man. C++-Klasse Data member: Zeiger vom Typ der C++- Klasse Data member: Zeiger vom Typ der C++- Klasse In der managed Klasse müssen die Konstruktoren nachgebildet werden In der managed Klasse müssen die Konstruktoren nachgebildet werden In der Dispose-Methode der managed Klasse die Instanz der unmanaged Klasse zerstören In der Dispose-Methode der managed Klasse die Instanz der unmanaged Klasse zerstören Alle Methoden in der managed Klasse implementieren Alle Methoden in der managed Klasse implementieren
24
Wrapper-Klassen Destruktoren Destruktoren Sowohl den Destruktor als auch die Dispose-Methode implementieren Sowohl den Destruktor als auch die Dispose-Methode implementieren Wrapper-Klasse von IDisposable ableiten Wrapper-Klasse von IDisposable ableiten Selbst-gesteuertes Zerstören des Objektes durch Dispose-Aufruf Selbst-gesteuertes Zerstören des Objektes durch Dispose-Aufruf Dispose vergessen: Garbage Collector schlägt mit dem Destruktor zu Dispose vergessen: Garbage Collector schlägt mit dem Destruktor zu System.GC.SupressFinalize in der Dispose- Methode nicht vergessen System.GC.SupressFinalize in der Dispose- Methode nicht vergessen
25
Probleme mit Wrappern Variable Parameteranzahl Variable Parameteranzahl Daten-Marshaling Daten-Marshaling Default Argumente Default Argumente Destruktoren (Garbage Collector) Destruktoren (Garbage Collector) Properties Properties Vergleichsoperatoren mit Overloading Vergleichsoperatoren mit Overloading
26
.NET-Code aus unman. Code Man kann.NET-Komponenten aus altem Code aufrufen Man kann.NET-Komponenten aus altem Code aufrufen CCW = COM Callable Wrapper CCW = COM Callable Wrapper using System.Runtime.InteropServices; using System.Runtime.InteropServices; Attribut [ClassInterface(ClassInterfaceType.AutoDual)] vor der Klasse definieren Attribut [ClassInterface(ClassInterfaceType.AutoDual)] vor der Klasse definieren Assembly in das Verzeichnis des Clients kopieren Assembly in das Verzeichnis des Clients kopieren TypeLib mit TLBEXP erzeugen TypeLib mit TLBEXP erzeugen Registrieren mit REGASM Registrieren mit REGASM
27
Migration: Grundsätzliche Überlegungen Es gibt verschiedene Arten von Code Es gibt verschiedene Arten von Code Algorithmen Algorithmen API-intensiver Code API-intensiver Code MFC-intensiver Code (UI-Code) MFC-intensiver Code (UI-Code) ATL-intensiver Code (COM/DCOM) ATL-intensiver Code (COM/DCOM) Alle Codearten erfordern einen anderen Migrationsaufwand Alle Codearten erfordern einen anderen Migrationsaufwand
28
Grundsätzliche Überlegungen Was erschwert eine Migration? Was erschwert eine Migration? Monolithischer Code Monolithischer Code Die Verwendung von Klassen-Bibliotheken Die Verwendung von Klassen-Bibliotheken Besonders dann, wenn die Klassen als Code in das Projekt aufgenommen wurden Später: Wrapper-Klassen Besonders dann, wenn die Klassen als Code in das Projekt aufgenommen wurden Später: Wrapper-Klassen Viel UI-Code Viel UI-Code Templates (Generische Datentypen) Templates (Generische Datentypen) Multiple Inheritance Multiple Inheritance
29
Grundsätzliche Überlegungen Was erschwert eine Migration? Was erschwert eine Migration? Klassen, welche im Destruktor die Resourcenverwaltung implementiert haben (Thema: Garbage Colletion) Klassen, welche im Destruktor die Resourcenverwaltung implementiert haben (Thema: Garbage Colletion) Code, der intensiv mit Zeigern arbeitet Code, der intensiv mit Zeigern arbeitet Code mit vielen API-Aufrufen Code mit vielen API-Aufrufen
30
Grundsätzliche Überlegungen Was erleichtert die Migration? Was erleichtert die Migration? Komponenten-orientierter Code Komponenten-orientierter Code Mehrschichtiges Applikations-Design Mehrschichtiges Applikations-Design Wichtig ist eine gute Trennung von UI und Business-Logik Wichtig ist eine gute Trennung von UI und Business-Logik Code in COM-Komponenten ist nützlich Code in COM-Komponenten ist nützlich Code in DLLs ist nützlich Code in DLLs ist nützlich
31
Grundsätzliche Überlegungen Eine Migration sollte nach Möglichkeit in mehreren kleinen Schritten durchgeführt werden Eine Migration sollte nach Möglichkeit in mehreren kleinen Schritten durchgeführt werden Was kann zunächst ohne Migration wiederverwendet werden? Was kann zunächst ohne Migration wiederverwendet werden? COM-Komponenten COM-Komponenten Windows-DLLs Windows-DLLs Der erste Schritt soll kurz sein! Der erste Schritt soll kurz sein! COM-Komponenten und DLLs sind aber auch am leichtesten zu portieren COM-Komponenten und DLLs sind aber auch am leichtesten zu portieren
32
Grundsätzliche Überlegungen Komplexe Codeteile zunächst einmal als unmanaged Code übernehmen Komplexe Codeteile zunächst einmal als unmanaged Code übernehmen Unsaubere Codeteile in managed Code portieren Unsaubere Codeteile in managed Code portieren Resourcen-intensive in managed Code portieren (Ausnutzung des Garbage Collectors) Resourcen-intensive in managed Code portieren (Ausnutzung des Garbage Collectors)
33
Grundsätzliche Überlegungen Vor der Migration: Vor der Migration: Test- Szenarien mit der alten Applikation generieren Test- Szenarien mit der alten Applikation generieren Während der Migration kann immer wieder vergleichend getestet werden Während der Migration kann immer wieder vergleichend getestet werden Migrieren Sie keine Projekte, die im Moment in der Entwicklungsphase sind Migrieren Sie keine Projekte, die im Moment in der Entwicklungsphase sind
34
Zusammenfassung Microsoft hat viel für die Interoperabilität von altem und.NET- Code getan Microsoft hat viel für die Interoperabilität von altem und.NET- Code getan Die Investitionen werden weitgehend geschützt Die Investitionen werden weitgehend geschützt Eine Applikation kann Schritt für Schritt migriert werden Eine Applikation kann Schritt für Schritt migriert werden Wichtig: Komponenten müssen vorhanden sein Wichtig: Komponenten müssen vorhanden sein
35
Questions and Answers
36
Further Information Microsoft Visual C++.NET Compiler Migration Guide http://www.gotdotnet.com/team/cplusplus/articles/compmig.doc Microsoft Visual C++.NET Compiler Migration Guide http://www.gotdotnet.com/team/cplusplus/articles/compmig.doc Managed Extensions for C++ Migration Guide http://www.gotdotnet.com/team/cplusplus/articles/mcmigrate.doc Managed Extensions for C++ Migration Guide http://www.gotdotnet.com/team/cplusplus/articles/mcmigrate.doc
37
Glossary Managed Code: Code, der unter der Kontrolle der.NET-Common Language Runtime läuft. Managed Code: Code, der unter der Kontrolle der.NET-Common Language Runtime läuft. Unmanaged Code: Prozessor-abhängiger Maschinencode. Unmanaged Code: Prozessor-abhängiger Maschinencode. CLR: Common Language Runtime; gemeinsame Runtime für alle.NET- Sprachen. CLR: Common Language Runtime; gemeinsame Runtime für alle.NET- Sprachen. GC: Garbage Collector; verwaltet den Speicher bei.NET-Anwendungen; zerstört bei Bedarf die nicht mehr referenzierten Objekte im Speicher. GC: Garbage Collector; verwaltet den Speicher bei.NET-Anwendungen; zerstört bei Bedarf die nicht mehr referenzierten Objekte im Speicher. (MS-) IL-Code: Microsoft Intermediate Language; Platform- unabhängiger Zwischencode, der von den.NET-Sprach-Compilern erzeugt wird; wird vom JIT-Compiler zur Laufzeit in nativen Maschinencode übersetzt. (MS-) IL-Code: Microsoft Intermediate Language; Platform- unabhängiger Zwischencode, der von den.NET-Sprach-Compilern erzeugt wird; wird vom JIT-Compiler zur Laufzeit in nativen Maschinencode übersetzt. JIT-Compiler: Just In Time-Compiler; übersetzt zur Laufzeit den MS-IL- Code in native Maschinensprache. JIT-Compiler: Just In Time-Compiler; übersetzt zur Laufzeit den MS-IL- Code in native Maschinensprache. ILDASM: Tool zum Anschauen des MS-IL-Codes in einer.NET-EXE-Datei. ILDASM: Tool zum Anschauen des MS-IL-Codes in einer.NET-EXE-Datei. RCW: Runtime Callable Wrapper; Wrapper-Klasse, die den Aufruf von unmanaged COM-Komponenten aus managed Code ermöglicht RCW: Runtime Callable Wrapper; Wrapper-Klasse, die den Aufruf von unmanaged COM-Komponenten aus managed Code ermöglicht
38
Ihr Potenzial. Unser Antrieb.
Ähnliche Präsentationen
© 2025 SlidePlayer.org Inc.
All rights reserved.