Udostępnij za pośrednictwem


Jak: MARSZAŁEK osadzone za pomocą funkcji PInvoke wskaźniki

Funkcje, które są implementowane w bibliotekach DLL niezarządzanego może być wywołana z kodu zarządzanego przy użyciu funkcji platformy wywołać (P/Invoke).Jeśli kod źródłowy dla biblioteki DLL nie jest dostępna, P/Invoke jest jedyną opcją współdziałanie.W odróżnieniu jednak od innych.NET języki Visual C++ stanowi alternatywę dla P/Invoke.Aby uzyskać więcej informacji, zobacz Za pomocą Interop C++ (niejawna PInvoke) i Jak: MARSZAŁEK osadzone wskaźników przy C++ Interop.

Przykład

Przekazując struktur do kodu macierzystego wymaga utworzeniu struktury zarządzanych równoważne pod względem układu danych do struktury macierzystym.Jednakże struktur, które zawierają wskaźniki wymagają specjalnego traktowania.Dla każdego wskaźnika osadzony w strukturze macierzystym zarządzanych wersję struktury powinny zawierać wystąpienia IntPtr typu.Ponadto pamięci dla tych wystąpień muszą być wyraźnie przydzielone, zainicjowany i zwolniony przy użyciu AllocCoTaskMem, StructureToPtr, i FreeCoTaskMem metody.

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 strukturę o nazwie ListString, która zawiera wskaźnik i funkcję o nazwie TakesListStruct.Moduł zarządzany jest przywóz funkcji TakesListStruct i definiuje strukturę o nazwie MListStruct, które jest równoważne z ListStruct macierzystego, z zastrzeżeniem, że podwójne * jest reprezentowana w aplikacji wiersza polecenia IntPtr instancji.Przed wywołaniem metody TakesListStruct, główna funkcja alokuje i inicjuje pamięci, która odwołuje się do tego pola.

Moduł zarządzany jest kompilowana/CLR, ale/CLR: również czystego programu works.

// TraditionalDll6.cpp
// compile with: /EHsc /LD
#include <stdio.h>
#include <iostream>
#define TRADITIONALDLL_EXPORTS
#ifdef TRADITIONALDLL_EXPORTS
#define TRADITIONALDLL_API __declspec(dllexport)
#else
#define TRADITIONALDLL_API __declspec(dllimport)
#endif

#pragma pack(push, 8)
struct ListStruct {
   int count;
   double* item;
};
#pragma pack(pop)

extern "C" {
   TRADITIONALDLL_API void TakesListStruct(ListStruct);
}

void TakesListStruct(ListStruct list) {
   printf_s("[unmanaged] count = %d\n", list.count);
   for (int i=0; i<list.count; i++)
      printf_s("array[%d] = %f\n", i, list.item[i]);
}

// EmbeddedPointerMarshalling.cpp
// compile with: /clr
using namespace System;
using namespace System::Runtime::InteropServices;

[StructLayout(LayoutKind::Sequential, Pack=8)]
value struct MListStruct {
   int count;
   IntPtr item;
};

value struct TraditionalDLL {
    [DllImport("TraditionalDLL6.dll")]
   static public void TakesListStruct(MListStruct);
};

int main() {
   array<double>^ parray = gcnew array<double>(10);
   Console::WriteLine("[managed] count = {0}", parray->Length);

   Random^ r = gcnew Random();
   for (int i=0; i<parray->Length; i++) {
      parray[i] = r->NextDouble() * 100.0;
      Console::WriteLine("array[{0}] = {1}", i, parray[i]);
   }

   int size = Marshal::SizeOf(double::typeid);
   MListStruct list;
   list.count = parray->Length;
   list.item = Marshal::AllocCoTaskMem(size * parray->Length);

   for (int i=0; i<parray->Length; i++) {
      IntPtr t = IntPtr(list.item.ToInt32() + i * size);
      Marshal::StructureToPtr(parray[i], t, false);
   }

   TraditionalDLL::TakesListStruct( list );
   Marshal::FreeCoTaskMem(list.item);
}

Uwaga, że żadna jego część biblioteki DLL jest narażony na kod zarządzany, przy użyciu tradycyjnych # dołączona dyrektywa.W rzeczywistości biblioteki DLL jest dostępny tylko w czasie wykonywania, problemy z funkcjami przywożone z DllImportAttribute nie będą wykrywane w czasie kompilacji.

Zobacz też

Inne zasoby

Za pomocą jawnego PInvoke w C++ (atrybut DllImport)