Megjegyzés
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhat bejelentkezni vagy módosítani a címtárat.
Az oldalhoz való hozzáféréshez engedély szükséges. Megpróbálhatja módosítani a címtárat.
A nem felügyelt DLL-ekben implementált függvények a platformhívási (P/Invoke) funkcióval meghívhatók felügyelt kódból. Ha a DLL forráskódja nem érhető el, a P/Invoke az egyetlen lehetőség az együttműködésre. Más .NET-nyelvektől eltérően azonban a Visual C++ alternatívát kínál a P/Invoke helyett. További információért lásd: A C++ Interop (Implicit P/Invoke) és a Beágyazott mutatók kezelése C++ Interop használatával.
példa
A struktúrák natív kódba való továbbításához létre kell hozni egy olyan felügyelt struktúrát, amely az adatelrendezés szempontjából egyenértékű a natív struktúrával. A mutatókat tartalmazó struktúrák azonban speciális kezelést igényelnek. A natív struktúra minden beágyazott mutatója esetében a struktúra felügyelt verziójának tartalmaznia kell egy IntPtr ilyen típusú példányt. Emellett ezeknek a példányoknak a memóriáját explicit módon kell lefoglalni, inicializálni és felszabadítani a AllocCoTaskMem, StructureToPtr és FreeCoTaskMem metódusok használatával.
A következő kód egy nem felügyelt és egy felügyelt modulból áll. A nem felügyelt modul egy DLL, amely egy olyan függvényt határoz meg, amely egy mutatót tartalmazó struktúrát ListString és egy úgynevezett TakesListStructfüggvényt fogad el.
// 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]);
}
A felügyelt modul egy parancssori alkalmazás, amely importálja a TakesListStruct függvényt, és meghatároz egy, a natívval MListStruct egyenértékű struktúrátListStruct, azzal a különbséggel, hogy az double* egy példánysal IntPtr van ábrázolva. A hívás TakesListStructelőtt a main függvény lefoglalja és inicializálja a mező által hivatkozott memóriát.
// 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);
}
A DLL egyetlen része sem érhető el a feldolgozott kód számára a hagyományos #include direktíva használatával. Valójában a DLL csak futtatókörnyezetben érhető el, így a használatával DllImportAttribute importált függvényekkel kapcsolatos problémák fordításkor nem észlelhetők.
Lásd még
Explicit P/Invoke használata c++ (DllImport attribútum) nyelven