Jak: tablice MARSZAŁEK przy użyciu funkcji PInvoke
W tym temacie wyjaśniono jak native funkcje, których ciągi c stylu można wywołać przy użyciu środowiska CLR typu string String za pomocą.NET Framework platformy wywołać pomocy technicznej.Visual C++ programiści są zachęcani do zamiast korzystać z funkcji współdziałania z modelem C++ (jeśli możliwe), ponieważ P/Invoke zawiera niewiele raportowanie błędów kompilacji, nie jest typu bezpiecznej i może być uciążliwe do wdrożenia.Jeśli niezarządzanego API jest dostarczana jako biblioteki DLL i kod źródłowy nie jest dostępny, P/Invoke jest jedyną opcją (w przeciwnym wypadku zobacz Za pomocą Interop C++ (niejawna PInvoke)).
Przykład
Ponieważ tablice macierzystych i zarządzanych określono inaczej w pamięci, przekazując je pomyślnie granice zarządzanych/niezarządzanych wymaga konwersji lub przekazywania międzyprocesowego.W tym temacie demonstruje, jak tablica elementów prostej (blitable) mogą być przekazywane do macierzystych funkcji z kodu zarządzanego.
Podobnie jak w zarządzanych/niezarządzanych danych kierowanie ogólnie rzecz biorąc, DllImportAttribute atrybut jest używany do utworzenia punktu wejścia zarządzanych dla każdej funkcji macierzystego, który będzie używany.W odniesieniu do funkcji, które tablice jako argumenty MarshalAsAttribute należy użyć atrybutu również określić kompilator, jak zorganizować dane.W poniższym przykładzie LPArray wyliczenie jest używany do wskazania, że tablicy zarządzane będą organizowane jako tablica c styl.
Poniższy kod składa się z niezarządzanych i zarządzanych modułu.Moduł niezarządzanego to biblioteki DLL, która definiuje funkcję, która akceptuje tablica wartości całkowitych.Drugi moduł jest zarządzanej aplikacji wiersza polecenia, że przywóz tej funkcji, ale definiuje ją z tablicy i używa MarshalAsAttribute atrybutu, aby określić, że tablicy ma być konwertowany do tablicy macierzysty, gdy wywoływana.
Moduł zarządzany jest kompilowana/CLR, ale/CLR: również czystego programu works.
// 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]);
}
Uwaga, że żadna jego część biblioteki DLL jest narażony na kod zarządzany za pośrednictwem tradycyjnych # dołączona dyrektywa.W rzeczywistości, ponieważ biblioteka DLL jest dostępny tylko w czasie wykonywania, problemy z funkcjami przywożone z DllImportAttribute nie będą wykrywane w czasie kompilacji.