1 / 49

Взаимодействие с неуправляван код

Програмиране за .NET Framework. http:// www.nakov.com / dotnet-project /. Взаимодействие с неуправляван код. Мартин Кулов. Изпълнителен директор CodeAttest. www.codeattest.com. Необходими знания. Базови познания за общата система от типове в .NET (Common Type System)

arnav
Download Presentation

Взаимодействие с неуправляван код

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Програмиране за .NET Framework http://www.nakov.com/dotnet-project/ Взаимодействиес неуправляван код Мартин Кулов Изпълнителен директор CodeAttest www.codeattest.com

  2. Необходими знания • Базови познания за общата система от типове в .NET (Common Type System) • Базови познания за езика C# • Базови познания за езика C++ • Базови познания за технологията COM • Базови познания за програмиране под Win32 със C и C++ • Познания за атрибутите в .NET Framework

  3. Съдържание • Какво е взаимодействие? • Платформено извикване (P/Invoke) • Атрибут DllImport • Преобразуване на данни (marshalling) • Преобразуване на структури • Преобразуване на класове • Преобразуване на низове • Атрибут MarshalAs • Имплементиране на функция за обратно извикване

  4. Съдържание (2) • Взаимодействие с COM • Извикване на COM компонент от управляван код • Runtime Callable Wrapper (RCW) • Разкриване на .NET компонент като COM компонент • COM Callable Wrapper (CCW) • Изисквания към .NET типове за ползване от COM • Взаимодействие със C++ (IJW) • Препоръки за използване на .NET типове от COM

  5. Какво е взаимодействие? • Microsoft.NET Framework е сравнително нова технология • Съществува огромно количество готов неуправляван код • Предимствата на управлявания код • Безопасност на типовете • Защита на паметта • Отражение на типовете • Обща среда или виртуална машина • CLR срещу JVM

  6. Среда за контролирано изпълнение .NET .NET Framework .NET приложение .NET Framework Class Libraries Common Language Runtime (CLR) Platform Interop COM Windows API Windows Kernel

  7. Архитектурата на JVM Java Platform Java приложение Java Class Libraries Java Virtual Machine (JVM) JNI COM Windows API Windows Kernel

  8. Платформено извикване (P/Invoke) • Подходящ за сравнително прости Windows функции (simple flat API) • Подходящ за малък брой методи от неуправляван код • Атрибутът DllImportслужи за извикване на неуправляван код • За удобство DLL функциите могат да се организират в клас

  9. Атрибут DllImport • Използва се за дефиниране на връзка с неуправляван код • Прилага се върху методи • При конструиране се указва името на DLL, който съдържа метода • Полето EntryPoint указва името на извиквания метод • Полето CharSet определя как да се кодират символните низове • Полето SetLastError дава възможност за извличане на грешка

  10. Как работи P/Invoke? • Намира и зарежда в паметта указания DLL (изпълнява се само веднъж) • Зарежда адреса на функцията, подава аргументите й и преобразува данните • Подава контрола на неуправлявания код • P/Invoke може да хвърли изключение от неуправлявания код

  11. P/Invoke – пример static IntPtr IDI_ASTERISK = (IntPtr) 32516; [DllImport("user32.dll", EntryPoint="LoadIconW", ExactSpelling=true, CharSet=CharSet.Unicode)] public static extern IntPtr LoadPredefinedIcon( IntPtr hinst, IntPtr icon); private void Form1_Load(object sender, System.EventArgs e) { // извличаме манипулатора на системната икона IntPtr hicon = LoadPredefinedIcon(IntPtr.Zero, IDI_ASTERISK); // създаваме нов обект икона от получения манипулатор Icon icon = Icon.FromHandle(hicon); // променяме иконата на главния прозорец this.Icon = (Icon) icon.Clone(); }

  12. Командата DUMPBIN • Стартира се от командния ред • Част е от MS Visual C++ • Позволява разглеждането на външните функции на даден DLL • Пример: DUMPBIN /EXPORTS C:\WINDOWS\system32\user32.dll … ordinal hint RVA name … 446 1BD 0000CBBB LoadIconA 447 1BE 000188E3 LoadIconW …

  13. Демонстрация #1 • Използване на P/Invoke

  14. Преобразуване на данни (marshalling) • Различни платформи – различни типове • Необходимост от преобразуване • Прави се автоматично (standard interop marshaller) • Може да заеме допълнително памет • Може да се промени стандартното действие

  15. Преобразуване – съответствия

  16. Преобразуване на структури • Структурите се предават по стойност • Използват се, когато неуправляван код използва предаване по стойност или чрез указател • Атрибутът StructLayout дефинира как да се преобразува структурата към неуправляван код • LayoutKind.Sequential • LayoutKind.Explicit • DLLFunc(POINT x)  ManagedFunc(POINT x) • DLLFunc(POINT* x)  ManagedFunc(ref POINT x)

  17. Преобразуване на структури – пример [StructLayout(LayoutKind.Explicit)] public struct SYSTEM_INFO { [FieldOffset(0)] public UInt16 ProcessorArchitecture; [FieldOffset(4)] public UInt32 PageSize; [FieldOffset(20)] public UInt32 NumberOfProcessors; [FieldOffset(24)] public UInt32 ProcessorType; [FieldOffset(28)] public UInt32 AllocationGranularity; [FieldOffset(30)] public UInt16 ProcessorLevel; } [DllImport("kernel32.dll", EntryPoint="GetNativeSystemInfo")] public static extern void GetSysInfo( ref SYSTEM_INFO sysinfo);

  18. Преобразуване на класове • Класовете се предават по адрес • Използват се при единичен или двоен указател • Атрибутът StructLayoutсе прилага и за класове DLLFunc(Job* x)  ManagedFunc(Job x) DLLFunc(Job** x)  ManagedFunc(ref Job x)

  19. Преобразуване на низове • Символните низове в .NET са постоянни (immutable) • Символните низове в неуправляван код са просто адрес в паметта • Могат да имат различно кодиране • Атрибутът MarshalAs позволява правилното преобразуване • Когато символният низ е с неопределена дължина, се използва класът StringBuilder

  20. Атрибут MarshalAs • Указва начина на преобразуване • Прилага се върху параметри, полета и резултат, когато има двусмислие • Не е задължителен • При конструиране се указва неуправляван тип, към които ще се преобразува • Полето SizeConst указва броя на знаците на подавания низ по стойност

  21. Преобразуване – пример

  22. Преобразуване – пример [DllImport("kernel32.dll", EntryPoint="GetModuleFileName", ExactSpelling=false, CharSet=CharSet.Auto)] public static extern UInt32 GetModuleFileName(IntPtr hModule, StringBuilder lpFileName, UInt32 nSize); [STAThread] static void Main(string[] args) { StringBuilder moduleName = new StringBuilder(10); UInt32 uiSize = GetModuleFileName(IntPtr.Zero, moduleName, (uint) moduleName.Capacity + 1); moduleName.Length = (int) uiSize; Console.WriteLine("Executable path: {0}", moduleName.ToString()); }

  23. Имплементиране на функция за обратно извикване • Функцията за обратно извикване(callback) служи за получаване на резултат от друга функция, която вие сте извикали • Неуправляваният код извиква функция от управлявания код • В управлявания код се дефинира променлива от тип delegate BOOL EnumWindows(WNDENUMPROC lpEnumFunc, LPARAM lParam) public delegate bool CallBack(int hWnd, int lParam);

  24. Демонстрация #2 • Преобразуване на данни

  25. Взаимодействие с COM • Какво е COM? • COM = Common Object Model – компонентен модел, използван широко при Win32 приложения • COM осигурява взаимодействие между Win32 приложения посредством компоненти • Интерфейсът IUnknown • Имплементира се задължително от всички COM компоненти • AddRef, Release – отброяват референциите към компонента (reference counting) • QueryInterface – открива интерфейсите, които компонентът поддържа (като reflection)

  26. Взаимодействие с COM • GUID – 128-битово число, което уникално идентифицира COM интерфейс, например: • {645FF040-5081-101B-9F08-00AA002F954E} • Интерфейсът IDispatch • Предоставя достъп по време на изпълнение до свойствата и методите на компонента (като reflection в .NET) • In-Process и Out-of-Process COM сървъри • In-Process – DLL библиотеки, работят в адресното пространство на клиента • Out-of-Process – отделни изпълними приложения (EXE), работят в отделно адресно пространство

  27. Взаимодействие с COM • Модели за COM компоненти STA и MTA • Single-Threaded Apartment – всяка нишка си има собствен апартамент, няма общи данни, няма нужда от синхронизация • Multithreaded Apartment – всички нишки споделят общ апартамент (общи данни), синхронизацията е ръчна • Типови библиотеки (Type Libraries) • Съдържат описание на COM компоненти (като метаданните в асемблитата) • Представляват бинарни (.tlb) файлове • Описват типове, класове, структури и др. • ActiveX – разширение на COM модела, което позволява работа в мрежова среда

  28. Извикване на COM компонент от управляван код • Необходимост от Interop асембли • Генериране на Interop асембли чрез Visual Studio .NET • Генериране на Interop асембли чрез tlbimp.exe • Програмно и нестандартно генериране на Interop асембли • Разгръщане (deployment) на Interop асембли

  29. Runtime Callable Wrapper (RCW) • COM обектите се достъпват през прокси наречено RCW • На всеки COM обект отговаря точно един RCW • Позволява стандартно преобразуване на данните • Достъпва стандартните COM интерфейси IDispatch, IErrorInfo, IUnknown

  30. IUnknown IDispatch COM обект COM обект IErrorInfo ICustomer IUnknown IDispatch IErrorInfo IWarehouse Извикване на COM компонент чрез RCW .NET клиент RCW .NET клиент RCW

  31. Демонстрация #3 • Използване на COM компонентата "Microsoft Web Browser"от VS.NET

  32. Разкриване на .NET компонент като COM компонент • Атрибутът GuidAttribute задава уникалния идентификатор на COM компонента (GUID) • Атрибутът ProgId задава текстов идентификатор на COM компонента • Aсемблито се регистрира в Windows Registry чрез regasm.exe или с VS.NET [GuidAttribute("D069E57A-981F-4841-8D68-E2F2342E92A2"), ProgId("SomeApplication.SomeClass")] public class SomeClass { // … }

  33. Разкриване на .NET компонент като COM компонент • Необходимост от типова библиотека • Генериране на типовата библиотека чрез tlbexp.exe • Използване на атрибути за контрол върху типовата библиотека • CoClassAttribute • ComVisibleAttribute • GuidAttribute • …

  34. COM Callable Wrapper (CCW) • .NET компонентите също се достъпват от COM клиенти през специално прокси • На всеки .NET компонент отговаря точно един CCW • Стандартно преобразуване на данните • Прокси класът имплементира стандартните COM интерфейси IUnknown, IDispatch, …

  35. Извикване на .NET компонент чрез CCW .NET обект COM клиент CCW COM клиент

  36. Изисквания към .NET типове за ползване от COM • Управляваните типове трябва да са public • Методи, свойства, полета и събития трябва да са public • Типовете трябва да имат публичен конструктор по подразбиране • Типовете не могат да са абстрактни • Препоръчва се класовете да имплементират интерфейс • Избягвайте статични методи

  37. Демонстрация #4 • Извикване на .NET компонент чрез CCW

  38. Взаимодействие със C++ (IJW) • C++ позволява директно извикване на неуправляван код (It Just Works) • Забавянето от IJW прокси имплементацията е малко (10-30 x86 инструкции за всяко извикване) • Изрично преобразуване на данните • Не се ползват атрибути • Позволява да се забележат по-лесно проблеми с производителността • Подходящ е за приложения, които ползват предимно неуправляван код

  39. IJW извикване от C++ – пример #using <mscorlib.dll> #include <stdio.h> #include <iostream> using namespace std; void main() { // Declare unmanaged pointer of type char* const char* str = "IJW (It Just Works)"; // Call unmanaged function "printf" printf("%s\n", str); // Call unmanaged function "ostream::operator <<" cout << str << endl; // Call managed function "Console::WriteLine" System::Console::WriteLine(str); }

  40. Препоръки за използванена .NET типове от COM • Използвайте “chunky” вместо “chatty” интерфейси • Имплементирайте IDisposable за неуправляваните ресурси • Избягвайте късно свързване • Указвайте името на метода който искате да извикате изрично • Оптимизирайте преобразуването на данни

  41. Препоръки за използванена .NET типове от COM • Може да използвате SuppressUnmanagedCode атрибута за критични по скорост извиквания • Следете броячите за взаимодействие • Брояч на CCW • Брояч на преобразуванията (marshallings) • Брояч на “корените” (stubs) • Използвайте CLR Spy за да откриете евентуални проблеми

  42. Демонстрация #5 • Използване наброячи и CLR Spy

  43. Взаимодействиес неуправляван код Въпроси?

  44. Упражнения • Имплементирайте Windows Forms приложение, което показва списък с активните в момента процеси. За всеки процес трябва да се покаже следната информация: идентификатора му (PID), името на файла, от който е зареден, приоритета му, обема на минималната и максималната му работна памет (working set). Използвайте Windows API функциите EnumProcesses(), OpenProcess(), GetModuleBaseName(), GetPriorityClass(), GetProcessWorkingSetSize() и CloseHandle(), като ги извиквате през P/Invoke . Дефинициите са в библиотеките kernel32.dll и psapi.dll. Използвайте документацията и примерите от MSDN за да видите как се използват посочените функции. Визуализирайте по подходящ начин извлечената информация за процесите.

  45. Упражнения • Имплементирайте Windows Forms приложение, което визуализира PDF документи с помощта на COM компонента "Adobe Acrobat Control for ActiveX". • Създайте Windows Forms контрола, която реализира играта "морски шах". Направете контролата достъпна като COM сървър. Направете HTML страница, с която да визуализирате контролата в Internet Explorer. • Реализирайте конзолно приложение, което по даден XML файл, съдържащ списък от фирми и информация за тях, генерира MS Excel документ, съдържащ същата информациявъв вид на таблица. Всяка фирма се описва с име, адрес и телефон. За връзка с MS Excel използвайте COM компонентата "Microsoft Office Spreadsheet".

  46. Използвана литература • MSDN Library – http://msdn.microsoft.com • Interoperating with Unmanaged Code • An Overview of Managed/Unmanaged Code Interoperability • Beyond (COM) Add Reference: Has Anyone Seen the Bridge? • Using the .NET Framework SDK Interoperability Tools • Calling a .NET Component from a COM Component • Microsoft Office and .NET Interoperability • The Myth of .NET Purity, Reloaded • Platform Invocation Services

  47. Използвана литература • MSDN Magazine – http://msdn.microsoft.com/msdnmag/ • Calling Win32 DLLs in C# with P/Invoke • Migrating Native Code to the .NET CLR • Improving .NET Application Performance and Scalability – MS Patterns and Practices – http://msdn.microsoft.com/library/en-us/dnpag/html/scalenet.asp • Chapter 7 – Improving Interop Performance • Checklist: Interop Performance • P/Invoke .NET: The Interop wiki! – http://www.pinvoke.net/

  48. Използвана литература • Microsoft .NET/COM Migration and Interoperability – http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnbda/html/cominterop.asp • CLR Spy – http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=C7B955C7-231A-406C-9FA5-AD09EF3BB37F

More Related