Platformani chaqirish bo'yicha xizmatlar - Platform Invocation Services

Platformani chaqirish bo'yicha xizmatlar, odatda deb nomlanadi P / chaqirish, ning xususiyati Umumiy til infratuzilmasi kabi dasturlar Microsoft "s Umumiy til ishlash vaqti, bu imkon beradi boshqariladigan kod qo'ng'iroq qilmoq mahalliy kod.

C # yoki VB.NET kabi boshqariladigan kod .NET Frameworkni tashkil etadigan kutubxonalarda belgilangan sinflarga, usullarga va turlarga mahalliy kirish imkoniyatini beradi. .NET Framework keng funktsiyalar to'plamini taqdim etsa-da, odatda boshqarilmaydigan kodlarda yozilgan yoki boshqarilmaydigan kodlarda yozilgan uchinchi tomon kutubxonalarida ishlaydigan ko'plab quyi darajadagi operatsion tizim kutubxonalariga kirish imkoni bo'lmasligi mumkin. P / Invoke - dasturchi ushbu kutubxonalardagi funktsiyalarga kirish uchun foydalanishi mumkin bo'lgan usuldir. Ushbu kutubxonalardagi funktsiyalarga qo'ng'iroqlar boshqariladigan kod ichidagi boshqarilmaydigan funktsiya imzosini e'lon qilish orqali sodir bo'ladi, bu boshqa har qanday boshqariladigan usul kabi chaqirilishi mumkin bo'lgan haqiqiy funktsiya vazifasini bajaradi. Deklaratsiya kutubxonaning fayl yo'liga murojaat qiladi va funktsiyalar parametrlarini belgilaydi va boshqariladigan turlarga, odatda boshqariladigan turlarga va tilning umumiy ish vaqti (CLR) tomonidan boshqarilishi mumkin bo'lgan turlarga bevosita bog'liq bo'lishi mumkin. Boshqarilmaydigan ma'lumotlar turlari va boshqariladigan turlarga oddiy yashirin konvertatsiya qilish uchun juda murakkablashganda, ramka foydalanuvchiga funktsiya, qaytish va / yoki parametrlar bo'yicha atributlarni aniqlashga imkon beradi, chunki ma'lumotlar qanday qilib marshallanganligini aniq aniqlab olish uchun. buni bilvosita bajarishga urinishda istisnolarga olib kelish. Boshqariladigan kod dasturchilarida boshqarilmaydigan tillarda dasturlash bilan taqqoslaganda quyi darajadagi dasturlash tushunchalarining ko'p mavhumliklari mavjud. Natijada, faqat boshqariladigan kod tajribasiga ega dasturchi P / Invoke-dan foydalanishda ba'zi bir oddiy, ammo keng tarqalgan to'siqlarni engib o'tish uchun ko'rsatgichlar, tuzilmalar va mos yozuvlar orqali o'tish kabi dasturlash tushunchalarini o'rganishi kerak.

Arxitektura

Umumiy nuqtai

Hozirda qo'llanilayotgan P / Invoke-ning ikkita varianti:

Aniq

  • Mahalliy kod orqali import qilinadi dinamik bog'langan kutubxonalar (DLL)
  • Metadata Qo'ng'iroq qiluvchining yig'ilishiga kiritilgan mahalliy kod qanday chaqirilishini va ma'lumotlarga kirishni belgilaydi (odatda kompilyatorga marshal yelimini ishlab chiqarishda yordam berish uchun atribut manba ko'rsatgichlarini talab qiladi)
    • Ushbu ta'rif "Aniq" qismdir

Yashirin

  • Foydalanish orqali C ++ / CLI, dastur bir vaqtning o'zida boshqariladigan uyumni (ko'rsatgichlarni kuzatish yo'li bilan) va har qanday mahalliy xotira mintaqasidan aniq deklaratsiyasiz foydalanishi mumkin. (Yashirin)
  • Bunday holda asosiy foyda, agar asl ma'lumotlar tuzilmalari o'zgargan bo'lsa, nomlash mos keladigan bo'lsa, a o'zgarishlarni buzish oldini olish.
    • Ya'ni, tabiiy sarlavhada tuzilmalarni qo'shish / olib tashlash / qayta buyurtma qilish, agar tuzilma a'zolari nomlari ham o'zgarmagan bo'lsa, shaffof ravishda qo'llab-quvvatlanadi.

Tafsilotlar

P / Invoke-dan foydalanganda CLR tutqichlar DLL yuklash va konvertatsiya qilish boshqarilmaydigan oldingi turlari KTS turlari (shuningdek, parametrlarni marshalling).[1][iqtibos kerak ]Buni amalga oshirish uchun CLR:

  • Topadi DLL funktsiyani o'z ichiga olgan.
  • Yuklaydi DLL xotiraga.
  • Xotirada funktsiya manzilini topadi va uning argumentlarini suyakka, kerak bo'lganda marshaling ma'lumotlar.

P / Invoke standart (boshqarilmaydigan) foydalanish uchun foydalidir C yoki C ++ DLL-lar. Uni dasturchi keng imkoniyatlardan foydalanishi kerak bo'lgan hollarda ishlatishi mumkin Windows API tomonidan taqdim etilgan ko'plab funktsiyalar Windows kutubxonalari mavjud emasligi o'rash. Qachon Win32 API bilan ta'sirlanmaydi .NET Framework bunga o'ralgan API qo'lda yozilishi kerak.

Tuzoqlar

P / Invoke paketlarini yozish qiyin va xatolarga olib kelishi mumkin. Mahalliy DLL-lardan foydalanish dasturchining bundan foyda ko'rmasligini anglatadi turdagi xavfsizlik va axlat yig'ish odatda .NET muhitida taqdim etiladi. Agar ular noto'g'ri ishlatilsa, bu kabi muammolarni keltirib chiqarishi mumkin segmentatsiya xatolari yoki xotira sızdırıyor. Da foydalanish uchun meros vazifalarining aniq imzolarini olish .NET atrof-muhit qiyin bo'lishi mumkin, bu esa bunday muammolarga olib kelishi mumkin. Shu maqsadda bunday imzolarni olish uchun vositalar va veb-saytlar mavjud bo'lib, imzo muammolarini oldini olishga yordam beradi. [1]

Boshqa tuzoqlarga quyidagilar kiradi:

  • Noto'g'ri ma'lumotlarni moslashtirish foydalanuvchi tomonidan belgilangan turlari boshqariladigan tilda: kompilyatorlar yoki C dagi kompilyator ko'rsatmalariga qarab ma'lumotlarni moslashtirishning turli xil usullari mavjud va aniq aytishga e'tibor berish kerak CLR ma'lumotlarni qanday moslashtirish kerak noaniq turlari. Buning keng tarqalgan misoli .NET da ma'lumotlar turini a ni ifodalash uchun belgilashga urinish birlashma yilda C. Ikki xil o'zgaruvchilar xotirada bir-biriga to'g'ri keladi va ushbu ikkita o'zgaruvchini .NET turidagi turiga qarab belgilash ularni xotiradagi turli joylarda bo'lishiga olib keladi, shuning uchun muammoni tuzatish uchun maxsus atributlardan foydalanish kerak.
  • Boshqariladigan tilning axlat yig'uvchisi tomonidan ma'lumotlar joylashuviga aralashish: agar mos yozuvlar .NET-dagi usul uchun mahalliy bo'lsa va mahalliy funktsiyaga o'tkazilsa, boshqariladigan usul qaytib kelganda, axlat yig'uvchi ushbu ma'lumotnomani qaytarib olishi mumkin. Ob'ektga mos yozuvlar ekanligiga e'tibor berish kerak mahkamlangan, uni axlat yig'uvchi tomonidan yig'ish yoki ko'chirishni oldini olish, bu mahalliy modul tomonidan yaroqsiz kirishga olib keladi.

C ++ / CLI dan foydalanilganda, chiqarilgan CIL boshqariladigan uyumda joylashgan ob'ektlar va bir vaqtning o'zida har qanday manzilga mo'ljallangan mahalliy xotira joylashuvi bilan o'zaro aloqa qilishda bepul. Boshqariladigan uy-joy rezidenti ob'ektini oddiy "object-> field;" dan foydalanib chaqirish, o'zgartirish yoki qurish mumkin. qiymatlarni belgilash yoki usul qo'ng'iroqlarini ko'rsatish uchun yozuv. Har qanday keraksiz kontekstni almashtirishni bartaraf etish natijasida ishlashning sezilarli yutuqlari paydo bo'ladi, xotira talablari kamayadi (stacklar qisqaroq).

Bu yangi muammolar bilan birga keladi:

  • Kod ikki marta Thunkingga moyil[2] agar maxsus murojaat qilinmasa
  • The Loader Lock muammosi [3]

Ushbu ma'lumotnomalar, agar ular duch kelsa, ushbu masalaning har biri uchun echimlarni belgilaydi. Asosiy foyda - bu tuzilish deklaratsiyasini bekor qilish, maydonlarni deklaratsiyalash tartibi va hizalanish masalalari C ++ Interop kontekstida mavjud emas.

Misollar

Asosiy misollar

Ushbu birinchi oddiy misol, ma'lum bir narsaning versiyasini qanday olishni ko'rsatmoqda DLL:

DllGetVersion funktsiyasi imzosi Windows API:

HREZULT DllGetVersion(    DLLVERSIONINFO* pdvi)

P / chaqirish C # ni chaqirish uchun kod DllGetVersion funktsiyasi:

[DllImport ("shell32.dll")]statik tashqi int DllGetVersion(ref DLLVERSIONINFO pdvi);

Ikkinchi misolda faylga qanday qilib ikonkani chiqarish ko'rsatilgan:

ExtractIcon Windows API-dagi funktsiya imzosi:

HIKON ExtractIcon(          HINSTANCE hInst,    LPCTSTR lpszExeFileName,    UINT nIconIndex);

P / ni chaqirish uchun C # kodini chaqiring ExtractIcon funktsiyasi:

[DllImport ("shell32.dll")]statik tashqi IntPtr ExtractIcon(    IntPtr hInst,     [MarshalAs (UnmanagedType.LPStr)] mag'lubiyat lpszExeFileName,     uint nIconIndex);

Ushbu keyingi murakkab misol voqeani ikkita jarayon o'rtasida qanday bo'lishishni ko'rsatadi Windows platformasi:

CreateEvent funktsiya imzosi:

 Qo'l CreateEvent(     LPSECURITY_ATTRIBUTES lpEventAttributes,     BOOL bManualReset,     BOOL bInitialState,     LPCTSTR lpName );

P / ni chaqirish uchun C # kodini chaqiring CreateEvent funktsiyasi:

[DllImport ("kernel32.dll", SetLastError = true)]statik tashqi IntPtr CreateEvent(    IntPtr lpEventAttributes,     bool bManualReset,    bool bInitialState,     [MarshalAs (UnmanagedType.LPStr)] mag'lubiyat lpName);

Keyinchalik murakkab misol

// mahalliy deklaratsiyatypedef tuzilmaviy _PAIR { 	DWORD Val1; 	DWORD Val2; } Juftlik, *PPAIR;
// / clr bilan tuzilgan; boshqariladigan / boshqarilmaydigan #pragma-dan foydalanish ikki barobarga tushishiga olib kelishi mumkin;// .h o'z ichiga olgan mustaqil .cpp-dan foydalanishdan saqlaning.// bu .h faylida joylashgan bo'ladi.shablon<>mos ravishda CLR_PAIR^ marshal_as<CLR_PAIR^, Juftlik> (konst Juftlik&Src) {    // de-referansdan foydalanishga e'tibor bering. Bu sizning ishlatishingizga mos kelishi kerak.	CLR_PAIR^ Dest = gcnew CLR_PAIR;	Dest->Val1 = Src.Val1;	Dest->Val2 = Src.Val2;	qaytish Dest;};
CLR_PAIR^ md_pair1;CLR_PAIR^ md_pair2;Juftlik ona0,*ona1=&ona0;ona0 = NativeCallGetRefToMemory();// marshal_as dan foydalanish. Katta yoki tez-tez ishlatiladigan turlar uchun mantiqiy.md_pair1 = marshal_as<CLR_PAIR^>(*ona1);// To'g'ridan-to'g'ri maydondan foydalanishmd_pair2->Val1 = ona0.Val1;md_pair2->val2 = ona0.val2;qaytish(md_pair1); // C # ga qaytish

Asboblar

P / Invoke imzolarini ishlab chiqarishda yordam beradigan bir qator vositalar mavjud.

C ++ sarlavhali fayllarni va mahalliy fayllarni import qiladigan yordamchi dasturni yozish DLL fayllar va interfeys yig'ilishini ishlab chiqarish avtomatik ravishda juda qiyin bo'lib chiqadi. P / Invoke imzolari uchun bunday import qiluvchi / eksport qiluvchini ishlab chiqarishdagi asosiy muammo ba'zi C ++ funktsiyalarini chaqirish parametrlari turlarining noaniqligidir.

Bred Abrams bu borada shunday dedi: P / chaqirish muammosi.

Muammo quyidagi kabi C ++ funktsiyalarida:

__declspec(dlexport) bekor MyFunction(char *params);

Parametr uchun qanday turni ishlatishimiz kerak params bizning P / Invoke imzoimizda? Bu C ++ null tugatilgan satr bo'lishi mumkin yoki a bo'lishi mumkin char qatori yoki chiqishi bo'lishi mumkin char parametr. Shunday qilib biz foydalanishimiz kerak mag'lubiyat, StringBuilder, char [] yoki ref char ?

Ushbu masaladan qat'i nazar, P / Invoke imzolarini ishlab chiqarishni soddalashtirish uchun bir nechta vositalar mavjud.

Quyida keltirilgan vositalardan biri, xInterop C ++ .NET ko'prigi .NET dunyosida bir xil C ++ usulini bir nechta bekor qilishni amalga oshirish orqali ushbu muammoni hal qildi, ishlab chiquvchilar qo'ng'iroq qilish uchun to'g'ri birini tanlashlari mumkin.

PInvoke.net

PInvoke.net ko'p sonli standart Windows API-lari uchun P / Invoke imzolarini o'z ichiga olgan viki. U egalik qiladi Redgate dasturi va oyiga 50000 atrofida xit bor.

Imzolar viki foydalanuvchilari tomonidan qo'lda tayyorlanadi. Ularni a yordamida qidirish mumkin bepul addin ga Microsoft Visual Studio.

PInvoker

PInvoker mahalliy DLL va C ++ .h fayllarini import qiladigan va to'liq shakllangan va kompilyatsiya qilingan eksport dasturi P / chaqirish interl DLL-lar. PInvoker o'ziga xos .NET interfeysi sinflarida mahalliy ko'rsatgich funktsiyalari parametrlarini o'rash orqali noaniqlik muammosini engib chiqadi. P / Invoke usuli ta'riflarida standart .NET parametr turlarini ishlatish o'rniga (char [], mag'lubiyatva hokazo) P / Invoke funktsiya chaqiruvlarida ushbu interfeys sinflaridan foydalanadi.

Masalan, yuqoridagi misol kodini ko'rib chiqsak, PInvoker .NET ishlab chiqaradi P / chaqirish .NET interfeysi sinfini qabul qiluvchi funktsiya char * ko'rsatgich. Ushbu sinfning qurilishi a dan bo'lishi mumkin mag'lubiyat yoki a dan char [] qator. Ikkalasi uchun ham asl xotira tuzilishi bir xil, ammo har bir tur uchun tegishli interfeys sinfi konstruktorlari xotirani turli yo'llar bilan to'ldiradilar. .NET turini funktsiyaga qanday kiritish kerakligini hal qilish uchun javobgarlik ishlab chiquvchiga beriladi.

Microsoft Interop yordamchisi

Microsoft Interop yordamchisi yuklab olish uchun mavjud bo'lgan ikkilik fayllar va manba kodlari bilan ta'minlangan bepul vosita CodePlex. Bu litsenziyaga ega Microsoft cheklangan jamoat litsenziyasi (Ms-LPL).

Ikki qismdan iborat:

  • Mahalliy C ++ sarlavha fayl kodining kichik qismlarini o'z ichiga olgan konvertor tuzilmaviy va usul ta'riflari. Keyin C # P / Invoke kodini ishlab chiqaradi, bu sizning nusxangizni nusxalash va ilovalaringizga joylashtirish uchun.
  • O'tkazilgan Windows API doimiysi, usuli va tuzilish ta'riflari bo'yicha qidiriladigan ma'lumotlar bazasi.

Ushbu vosita kompilyatsiya qilingan DLL o'rniga C # manba kodini ishlab chiqargani uchun foydalanuvchi ishlatishdan oldin kodga zarur bo'lgan har qanday o'zgartirishlarni kiritishi mumkin. Shunday qilib, noaniqlik muammosi P / Invoke usuli imzosida foydalanish uchun ma'lum bir .NET turini tanlagan dastur tomonidan hal qilinadi va agar kerak bo'lsa foydalanuvchi buni kerakli turga o'zgartirishi mumkin.

P / chaqirish ustasi

The P / chaqirish ustasi Microsoft Interop Assistant-ga o'xshash usuldan foydalanadi, chunki u mahalliy C ++ .h fayl kodini qabul qiladi va sizning .NET dastur kodingizga kiritishingiz uchun C # (yoki VB.NET) kodini ishlab chiqaradi.

Bundan tashqari, qaysi ramka uchun maqsad qilishni xohlagan variantlar mavjud: ish stoli uchun .NET Framework yoki Windows Mobile aqlli qurilmalari uchun .NET Compact Framework (va Windows CE).

xInterop C ++ .NET ko'prigi

xInterop C ++ .NET ko'prigi .NET yig'ilishlariga kirish uchun mahalliy C ++ DLL-lari va C ++ ko'prigi uchun yaratilgan C # o'ralgan Windows dasturidir, u C # /. .NET-dan kirish mumkin.

Ushbu vosita mavjud bo'lgan C ++ DLL-laridan va unga tegishli sarlavha fayllaridan manba kodi bilan C # doka DLL-larini yaratadi, ular uchun C # doka DLL-ni yaratish uchun talab qilinadi. P / Invoke imzolari va ma'lumotlar marshingi dastur tomonidan yaratilgan. Natijada paydo bo'lgan C # o'ramida parametr turi .NET kodiga o'tkazilgan C ++ o'xshashining o'xshash interfeysi mavjud.

Ushbu vosita C ++ DLL-dan eksport qilinmagan shablon sinflarini taniydi va shablon sinfini o'rnatadi va uni qo'shimcha DLL-ga eksport qiladi va tegishli C ++ interfeysi .NET-da ishlatilishi mumkin.

Shuningdek qarang

Adabiyotlar

  1. ^ Parametrlarni marshalash umumiy atama bilan adashtirmaslik kerak marshalling, ma'no Serializatsiya. Marshallangan parametrlar CLR konvertatsiya qilinganidan keyin stack KTS turlari, lekin seriyalanmagan.
  2. ^ https://docs.microsoft.com/en-us/cpp/dotnet/double-thunking-cpp
  3. ^ https://docs.microsoft.com/en-us/cpp/dotnet/initialization-of-mixed-assemblies

Tashqi havolalar