Nasıl yapılır: PInvoke Kullanarak Dizileri Sıralama

Bu konu C türü dizgileri kabul eden yerel işlevlerin .NET Framework Platform Çağırma desteğini kullanan System::String CLR dize türünü String kullanarak nasıl çağrılacağını açıklar.Visual C++ programcılarının mümkünse C++ Interop özelliklerini kullanmaları önerilir çünkü P/Invoke çok az derleme zamanı hata raporlama sağlar, tür kullanımı uyumlu değildir ve uygulaması can sıkıcı olabilir.Yönetilmeyen API DLL olarak paketlenmişse ve kaynak kod kullanılabilir değilse, P/Invoke tek seçenektir, (ancak aksi durumda bkz. C++ Birlikte Çalışabilirliği Kullanma (Örtük PInvoke)).

Örnek

Yerli ve yönetilen diziler bellekte farklı düzenlendikleri için, bunları başarıyla yönetilen ve yönetilmeyen sınırlardan geçirmek dönüştürmeyi veya sıralamayı gerektirir.Bu konuda bir dizi basit (taşınabilir) öğenin nasıl yönetilen koddan yerel işleve geçirilebileceği gösterilmektedir.

Yönetilen ve yönetilmeyen veri sıralamada olduğu gibi DllImportAttribute özniteliği kullanılacak her bir yerel fonksiyon için bir yönetilen giriş noktası oluşturmak üzere kullanılır.Dizileri bağımsız değişkenler olarak alan işlevlerin olması durumunda MarshalAsAttribute özniteliği verinin nasıl sıralanacağını derleyiciye belirtmek için kullanılmalıdır.Aşağıdaki örnekte, LPArray numaralandırması, yönetilen dizinin C türü bir dizi olarak sıralanmış olduğunu belirtmek için kullanılır.

Aşağıdaki kod bir yönetilen ve bir yönetilmeyen modülden oluşmaktadır.Yönetilmeyen modül bir tamsayı dizisini kabul eden bir işlevi tanımlayan bir DLL modülüdür.İkinci modül, bu işlevi içeri aktaran bir yönetilen komut satırı uygulamasıdır, ancak bunu yönetilen bir dizi açısından tanımlar ve MarshalAsAttribute özniteliğini dizenin çağrıldığında yerel bir dizeye dönüştürülmesi gerektiğini belirtmek için kullanır.

Yönetilen modül /clr ile derlenir, ama /clr:pure de çalışır.

// TraditionalDll4.cpp
// compile with: /LD /EHsc
#include <iostream>

#define TRADITIONALDLL_EXPORTS
#ifdef TRADITIONALDLL_EXPORTS
#define TRADITIONALDLL_API __declspec(dllexport)
#else
#define TRADITIONALDLL_API __declspec(dllimport)
#endif

extern "C" {
   TRADITIONALDLL_API void TakesAnArray(int len, int[]);
}

void TakesAnArray(int len, int a[]) {
   printf_s("[unmanaged]\n");
   for (int i=0; i<len; i++)
      printf("%d = %d\n", i, a[i]);
}

// MarshalBlitArray.cpp
// compile with: /clr
using namespace System;
using namespace System::Runtime::InteropServices;

value struct TraditionalDLL {
   [DllImport("TraditionalDLL4.dll")]
   static public void TakesAnArray(
   int len,[MarshalAs(UnmanagedType::LPArray)]array<int>^);
};

int main() {
   array<int>^ b = gcnew array<int>(3);
   b[0] = 11;
   b[1] = 33;
   b[2] = 55;
   TraditionalDLL::TakesAnArray(3, b);

   Console::WriteLine("[managed]");
   for (int i=0; i<3; i++)
      Console::WriteLine("{0} = {1}", i, b[i]);
}

DLL'nin hiçbir bölümünün geleneksel #include yönergesi aracılığıyla yönetilen koda gösterilmeyeceğini unutmayın.Aslında, DLL'ye yalnızca çalışma zamanında erişilir, böylece DllImportAttribute ile içeri aktarılan işlevlerle ilgili sorunlar çalışma zamanında algılanmaz.

Ayrıca bkz.

Diğer Kaynaklar

C++'ta Açık PInvoke Kullanma (DllImport Özniteliği)