Udostępnij za pośrednictwem


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)