Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Funktioner som implementeras i ohanterade DLL:er kan anropas från hanterad kod med hjälp av P/Invoke-funktioner (Platform Invoke). Om källkoden för DLL inte är tillgänglig är P/Invoke det enda alternativet för samverkan. Men till skillnad från andra .NET-språk är Visual C++ ett alternativ till P/Invoke. Mer information finns i Använda C++ Interop (Implicit P/Invoke) och Så här gör du: Konvertera inbäddade pekare med C++ Interop.
Exempel
För att kunna skicka strukturer till inbyggd kod krävs att en hanterad struktur som är likvärdig när det gäller datalayout till den inbyggda strukturen skapas. Strukturer som innehåller pekare kräver dock särskild hantering. För varje inbäddad pekare i den interna strukturen ska den hanterade versionen av strukturen innehålla en instans av typen IntPtr . Dessutom måste minne för dessa instanser uttryckligen allokeras, initieras och släppas med metoderna AllocCoTaskMem, StructureToPtroch FreeCoTaskMem .
Följande kod består av en ohanterad och en hanterad modul. Den ohanterade modulen är en DLL som definierar en funktion som accepterar en struktur med namnet ListString som innehåller en pekare och en funktion som heter TakesListStruct.
// 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]);
}
Den hanterade modulen är ett kommandoradsprogram som importerar TakesListStruct funktionen och definierar en struktur som heter MListStruct som motsvarar den inbyggda ListStruct förutom att double* den representeras med en IntPtr instans. Innan den anropar TakesListStructmain allokerar och initierar funktionen det minne som det här fältet refererar till.
// 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);
}
Ingen del av DLL:n exponeras för den hanterade koden med hjälp av det traditionella #include direktivet. I själva verket nås DLL under körning, så problem i funktioner som importeras med hjälp av DllImportAttribute kan inte upptäckas vid kompilering.