Porady: kierowanie tablic za pomocą funkcji PInvoke
W tym temacie wyjaśniono sposób macierzysty funkcji, które akceptują stylu C ciągi mogą być wywoływane za pomocą CLR typu string String z pomocy technicznej o wywołanie platformy.NET Framework.Programiści Visual C++ są zachęcani do zamiast korzystać z funkcji C++ Interop (jeśli możliwe), ponieważ P i Invoke zawiera niewiele kompilacji raportowanie błędów, nie jest typu palety i może być uciążliwe do wdrożenia.Jeśli API niezarządzanego, jest dostarczana w bibliotece DLL i kod źródłowy nie jest dostępny, P/Invoke jest jedyną opcją (w przeciwnym wypadku zobacz Korzystanie z międzyoperacyjności języka C++ (niejawna funkcja PInvoke)).
Przykład
Ponieważ tablice macierzystego i zarządzane są określone inaczej w pamięci, przekazując je pomyślnie na granicy zarządzanych/niezarządzanych wymaga konwersji lub przekazywania międzyprocesowego.W tym temacie przedstawiono, jak szereg elementów proste (blitable) mogą być przekazywane do macierzystych funkcji z kodu zarządzanego.
Jak w zarządzanych/niezarządzanych dane organizacyjne w ogóle, DllImportAttribute atrybut jest używany do tworzenia zarządzany punkt wejścia dla każdej funkcji macierzystego, który będzie używany.W przypadku funkcje, których użycie tablic jako argumentów MarshalAsAttribute atrybutu musi także służyć do określania w kompilatorze jak można zorganizować dane.W poniższym przykładzie LPArray wyliczenie jest używany do wskazania, że zarządzanych tablicy będą organizowane jako tablica stylu C.
Poniższy kod składa się z modułu zarządzane i niezarządzane.Moduł niezarządzanych to biblioteki DLL, która definiuje funkcję, która przyjmuje tablicę liczb całkowitych.Drugi moduł to zarządzanej aplikacji wiersza polecenia, że przywóz tej funkcji, ale definiuje ją pod względem tablicy i używa MarshalAsAttribute atrybut, aby określić, że tablica ma być konwertowany do tablicy macierzystego po wywołaniu.
Moduł zarządzany jest skompilowany z/CLR, ale/CLR: pure działa jak również.
// 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]);
}
Należy zauważyć, że żadna część biblioteki DLL jest narażony na kod zarządzany za pośrednictwem tradycyjnych # dyrektywy include.W rzeczywistości, ponieważ biblioteka DLL jest dostępny tylko w czasie wykonywania, problemy z funkcjami są importowane z DllImportAttribute nie zostaną wykryte w czasie kompilacji.
Zobacz też
Inne zasoby
Używanie jawnej funkcji PInvoke w języku C++ (atrybut DllImport)