Sdílet prostřednictvím


Postupy: Zařazování polí pomocí volání nespravovaného kódu

Nativní funkce, které přijímají řetězce ve stylu jazyka C, můžete volat pomocí typu String řetězce CLR při použití podpory volání platformy .NET Framework (P/Invoke). Doporučujeme, abyste místo volání nespravovaného kódu používali funkce spolupráce C++, pokud je to možné. Volání nespravovaného kódu poskytuje zasílání zpráv o chybách v době kompilace, není typově bezpečné a nelze je implementovat. Pokud je nespravované rozhraní API zabalené jako knihovna DLL a zdrojový kód není k dispozici, je jediným parametrem volání nespravovaného kódu. V opačném případě se podívejte na použití zprostředkovatele komunikace C++ (implicitní volání nespravovaného kódu).)

Příklad

Vzhledem k tomu, že nativní a spravovaná pole jsou v paměti rozložena odlišně, předávání je úspěšně přes spravovanou nebo nespravovanou hranici vyžaduje převod nebo zařazování. Tento článek ukazuje, jak lze předat pole jednoduchých (blitelných) položek nativním funkcím ze spravovaného kódu.

Stejně jako u spravovaných nebo nespravovaných zařazování dat obecně platí, že DllImportAttribute se atribut používá k vytvoření spravovaného vstupního bodu pro každou použitou nativní funkci. Ve funkcích, které přebírají pole jako argumenty, MarshalAsAttribute musí být atribut použit k určení způsobu zařazování dat. V následujícím příkladu UnmanagedType se výčet používá k označení, že spravované pole je zařazováno jako pole ve stylu jazyka C.

Následující kód se skládá z nespravovaného a spravovaného modulu. Nespravovaný modul je knihovna DLL, která definuje funkci, která přijímá pole celých čísel. Druhý modul je spravovaná aplikace příkazového řádku, která importuje tuto funkci, ale definuje ji z hlediska spravovaného pole. Pomocí atributu MarshalAsAttribute určuje, že pole má být při zavolání převedeno na nativní pole.

// 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]);
}

Spravovaný modul je zkompilován pomocí /clr.

// 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]);
}

Prostřednictvím tradiční #include direktivy není pro spravovaný kód zpřístupněna žádná část knihovny DLL. Vzhledem k tomu, že knihovna DLL je přístupná pouze za běhu, nelze v době kompilace rozpoznat problémy s funkcemi importovanými pomocí DllImportAttribute .

Viz také

Použití explicitního volání nespravovaného kódu v jazyce C++ (DllImport atribut)