Anteckning
Å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.
Det här avsnittet beskriver hur du utökar marshaling-biblioteket för att tillhandahålla fler konverteringar mellan datatyper. Användare kan utöka marshaling-biblioteket för datakonverteringar som för närvarande inte stöds av biblioteket.
Du kan utöka marshaling-biblioteket på något av två sätt – med eller utan en marshal_context-klass. Läs avsnittet 'Översikt över marshaling i C++' för att bestämma om en omvandling kräver en kontext.
I båda fallen skapar du först en fil för nya konverteringar av marskalkning. Du gör det för att bevara standardbiblioteksfilerna för marshaling intakta. Om du vill portera ett projekt till en annan dator eller till en annan programmerare måste du kopiera den nya marshaling-filen tillsammans med resten av projektet. På så sätt garanteras användaren som tar emot projektet att ta emot de nya konverteringarna och behöver inte ändra några biblioteksfiler.
Utöka marshaling-biblioteket med en konvertering som inte kräver en kontext
Skapa en fil för att lagra de nya datastruktureringsfunktionerna, till exempel MyMarshal.h.
Inkludera en eller flera av marshal-biblioteksfilerna:
marshal.h för bastyper.
marshal_windows.h för windows-datatyper.
marshal_cppstd.h för C++ Standard Library-datatyper.
marshal_atl.h för ATL-datatyper.
Använd koden i slutet av de här stegen för att skriva konverteringsfunktionen. I den här koden är TO den typ som ska konverteras till, FROM är den typ som ska konverteras från och
fromär parametern som ska konverteras.Ersätt kommentaren om konverteringslogik med kod för att konvertera parametern
fromtill ett objekt av TYPEN TO och returnera det konverterade objektet.
namespace msclr {
namespace interop {
template<>
inline TO marshal_as<TO, FROM> (const FROM& from) {
// Insert conversion logic here, and return a TO parameter.
}
}
}
Utöka marshaling-biblioteket med en konvertering som kräver en kontext
Skapa en fil för att lagra de nya marshalfunktionerna, till exempel MyMarshal.h
Inkludera en eller flera av marshal-biblioteksfilerna:
marshal.h för bastyper.
marshal_windows.h för windows-datatyper.
marshal_cppstd.h för C++ Standard Library-datatyper.
marshal_atl.h för ATL-datatyper.
Använd koden i slutet av de här stegen för att skriva konverteringsfunktionen. I den här koden är TO den typ som ska konverteras till, FROM är den typ som ska konverteras från,
toObjectär en pekare där resultatet ska lagras ochfromObjectär parametern som ska konverteras.Ersätt kommentaren om initialisering med kod för att initiera
toPtrtill ett tomt lämpligt värde. Om det till exempel är en pekare anger du den tillNULL.Ersätt kommentaren om konverteringslogik med kod för att konvertera parametern
fromtill ett objekt av TYPEN TO . Det här konverterade objektet lagras itoPtr.Ersätt kommentaren om inställningen
toObjectmed kod för att ställa intoObjecttill ditt konverterade objekt.Ersätt kommentaren om att rensa interna resurser med kod för att frigöra allt minne som allokeras av
toPtr. OmtoPtrallokerat minne med hjälp avnew, använder dudeleteför att frigöra minnet.
namespace msclr {
namespace interop {
template<>
ref class context_node<TO, FROM> : public context_node_base
{
private:
TO toPtr;
public:
context_node(TO& toObject, FROM fromObject)
{
// (Step 4) Initialize toPtr to the appropriate empty value.
// (Step 5) Insert conversion logic here.
// (Step 6) Set toObject to the converted parameter.
}
~context_node()
{
this->!context_node();
}
protected:
!context_node()
{
// (Step 7) Clean up native resources.
}
};
}
}
Exempel: Utöka marshaling-biblioteket
I följande exempel utökas marshaling-biblioteket med en konvertering som inte kräver någon kontext. I det här exemplet konverterar koden medarbetarens information från en intern datatyp till en hanterad datatyp.
// MyMarshalNoContext.cpp
// compile with: /clr
#include <msclr/marshal.h>
value struct ManagedEmp {
System::String^ name;
System::String^ address;
int zipCode;
};
struct NativeEmp {
char* name;
char* address;
int zipCode;
};
namespace msclr {
namespace interop {
template<>
inline ManagedEmp^ marshal_as<ManagedEmp^, NativeEmp> (const NativeEmp& from) {
ManagedEmp^ toValue = gcnew ManagedEmp;
toValue->name = marshal_as<System::String^>(from.name);
toValue->address = marshal_as<System::String^>(from.address);
toValue->zipCode = from.zipCode;
return toValue;
}
}
}
using namespace System;
using namespace msclr::interop;
int main() {
NativeEmp employee;
employee.name = "Jeff Smith";
employee.address = "123 Main Street";
employee.zipCode = 98111;
ManagedEmp^ result = marshal_as<ManagedEmp^>(employee);
Console::WriteLine("Managed name: {0}", result->name);
Console::WriteLine("Managed address: {0}", result->address);
Console::WriteLine("Managed zip code: {0}", result->zipCode);
return 0;
}
I föregående exempel returnerar funktionen marshal_as ett handtag till de konverterade uppgifterna. Detta gjordes för att förhindra att ytterligare en kopia av data skapas. Att returnera variabeln direkt skulle ha en onödig prestandakostnad associerad med den.
Managed name: Jeff Smith
Managed address: 123 Main Street
Managed zip code: 98111
Exempel: Konvertera information om medarbetare
I följande exempel konverteras den anställdas information från en hanterad datatyp till en intern datatyp. Den här konverteringen kräver en kontext för datahantering.
// MyMarshalContext.cpp
// compile with: /clr
#include <stdlib.h>
#include <string.h>
#include <msclr/marshal.h>
value struct ManagedEmp {
System::String^ name;
System::String^ address;
int zipCode;
};
struct NativeEmp {
const char* name;
const char* address;
int zipCode;
};
namespace msclr {
namespace interop {
template<>
ref class context_node<NativeEmp*, ManagedEmp^> : public context_node_base
{
private:
NativeEmp* toPtr;
marshal_context context;
public:
context_node(NativeEmp*& toObject, ManagedEmp^ fromObject)
{
// Conversion logic starts here
toPtr = NULL;
const char* nativeName;
const char* nativeAddress;
// Convert the name from String^ to const char*.
System::String^ tempValue = fromObject->name;
nativeName = context.marshal_as<const char*>(tempValue);
// Convert the address from String^ to const char*.
tempValue = fromObject->address;
nativeAddress = context.marshal_as<const char*>(tempValue);
toPtr = new NativeEmp();
toPtr->name = nativeName;
toPtr->address = nativeAddress;
toPtr->zipCode = fromObject->zipCode;
toObject = toPtr;
}
~context_node()
{
this->!context_node();
}
protected:
!context_node()
{
// When the context is deleted, it will free the memory
// allocated for toPtr->name and toPtr->address, so toPtr
// is the only memory that needs to be freed.
if (toPtr != NULL) {
delete toPtr;
toPtr = NULL;
}
}
};
}
}
using namespace System;
using namespace msclr::interop;
int main() {
ManagedEmp^ employee = gcnew ManagedEmp();
employee->name = gcnew String("Jeff Smith");
employee->address = gcnew String("123 Main Street");
employee->zipCode = 98111;
marshal_context context;
NativeEmp* result = context.marshal_as<NativeEmp*>(employee);
if (result != NULL) {
printf_s("Native name: %s\nNative address: %s\nNative zip code: %d\n",
result->name, result->address, result->zipCode);
}
return 0;
}
Native name: Jeff Smith
Native address: 123 Main Street
Native zip code: 98111