Delen via


Instructies voor: Arrays marshallen met P/Invoke

U kunt systeemeigen functies aanroepen die tekenreeksen in C-stijl accepteren met behulp van het CLR-tekenreekstype String wanneer u ondersteuning voor .NET Framework Platform Invoke (P/Invoke) gebruikt. We raden u aan om de C++ Interop-functies te gebruiken in plaats van P/Invoke, indien mogelijk. P/Invoke biedt weinig rapportage van compilatiefouten, is niet type-veilig en kan vervelend zijn om te implementeren. Als de niet-beheerde API is verpakt als een DLL en de broncode niet beschikbaar is, is P/Invoke de enige optie. Anders, zie C++ interop gebruiken (impliciete P/invoke)).

Voorbeeld

Omdat systeemeigen en beheerde arrays anders in het geheugen worden ingedeeld, vereist het succesvol overbrengen over de beheerde/onbeheerde grens conversie of marshaling. In dit artikel wordt gedemonstreerd hoe een matrix met eenvoudige (blieerbare) items kan worden doorgegeven aan systeemeigen functies vanuit beheerde code.

Net als bij beheerde/onbeheerde data marshaling in het algemeen, wordt het DllImportAttribute kenmerk gebruikt om een beheerd toegangspunt te maken voor elke systeemeigen functie die wordt gebruikt. In functies die matrices als argumenten gebruiken, moet het MarshalAsAttribute kenmerk worden gebruikt om op te geven hoe de gegevens moeten worden gebruikt. In het volgende voorbeeld wordt de UnmanagedType opsomming gebruikt om aan te geven dat de beheerde matrix wordt marshaled als een C-stijlmatrix.

De volgende code bestaat uit een niet-beheerde en een beheerde module. De niet-beheerde module is een DLL die een functie definieert die een matrix met gehele getallen accepteert. De tweede module is een beheerde opdrachtregeltoepassing die deze functie importeert, maar definieert deze in termen van een beheerde matrix. Hierbij wordt het MarshalAsAttribute kenmerk gebruikt om op te geven dat de matrix moet worden geconverteerd naar een systeemeigen matrix wanneer deze wordt aangeroepen.

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

De beheerde module wordt gecompileerd met behulp van /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]);
}

Er wordt geen deel van het DLL-bestand blootgesteld aan de beheerde code via de traditionele #include richtlijn. Omdat het DLL-bestand alleen tijdens runtime wordt geopend, kunnen problemen in functies die met behulp van het gebruik DllImportAttribute worden geïmporteerd, niet worden gedetecteerd tijdens het compileren.

Zie ook

Expliciete P/Invoke gebruiken in C++ (DllImport kenmerk)