Jak: rozszerzenie kierującego biblioteki
W tym temacie wyjaśniono, jak rozszerzyć kierującego biblioteki, aby zapewnić więcej konwersje między typami danych.Użytkownicy mogą rozszerzać kierującego biblioteki dla wszelkich konwersji danych nie są obecnie obsługiwane przez bibliotekę.
Można rozszerzyć kierującego biblioteki w jeden z dwóch sposobów - z lub bez Klasa marshal_context.Przegląd Omówienie przekazywania międzyprocesowego w języku C++ tematu, aby ustalić, czy nowe konwersji wymaga kontekstu.
W obu przypadkach należy najpierw utworzyć plik dla nowej konwersji dotyczące organizowania.W takim w celu zachowania spójności standard przekazywania międzyprocesowego plików biblioteki.Jeśli port projektu do innego komputera lub innego programista musi skopiuj nowy plik kierującego wraz z pozostałej części projektu.W ten sposób użytkownik otrzymania projektu będzie gwarantowane do odbierania nowych konwersje i nie będą musiały zmodyfikować pliki biblioteki.
Aby rozszerzyć kierowanie biblioteka konwersji, które nie wymagają kontekstu
Tworzenie pliku do przechowywania nowych funkcji kierującego, na przykład MyMarshal.h.
Zawiera jeden lub więcej plików biblioteki MARSZAŁEK:
Marshal.h dla typów podstawowych.
marshal_windows.h dla typów danych systemu windows.
marshal_cppstd.h STL typów danych.
marshal_atl.h ATL typów danych.
Kod można stosować po zakończeniu tych czynności, aby napisać funkcję konwersji.Ten kod jest do konwersji na typ, od jest typ konwersji z, i from jest parametr do konwersji.
Zamień komentarz na temat konwersji logiki kod do konwersji from parametr na obiekt do typu i przywrócić przekonwertowanego obiektu.
namespace msclr {
namespace interop {
template<>
inline TO marshal_as<TO, FROM> (const FROM& from) {
// Insert conversion logic here, and return a TO parameter.
}
}
}
Aby rozszerzyć kierującego biblioteki z konwersji, która wymaga kontekstu
Tworzenie pliku do przechowywania nowych funkcji kierującego, na przykład MyMarshal.h.
Zawiera jeden lub więcej plików biblioteki MARSZAŁEK:
Marshal.h dla typów podstawowych.
marshal_windows.h dla typów danych systemu windows.
marshal_cppstd.h STL typów danych.
marshal_atl.h ATL typów danych.
Kod można stosować po zakończeniu tych czynności, aby napisać funkcję konwersji.Ten kod jest do konwersji na typ, od jest typu do konwertowania, toObject jest wskaźnik do przechowywania wyników, i fromObject jest parametr do konwersji.
Zamień komentarz na temat inicjowanie z kodem zainicjować toPtr na odpowiednią wartość pusta.Na przykład, jeśli wskaźnik, ustaw ją NULL.
Zamień komentarz na temat konwersji logiki kod do konwersji from parametr na obiekt z do typu.Ten obiekt przekonwertowany będą przechowywane w toPtr.
Zamień komentarz na temat ustawienia toObject kod, ustawić toObject do przekonwertowanego obiektu.
Zamień komentarz na temat czyszczenie zasoby macierzystych z kodu, aby zwolnić pamięć, wszelkie przyznane przez toPtr.Jeśli toPtr przydzielonej pamięci za pomocą new, użyj delete , aby zwolnić pamięć.
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.
}
};
}
}
Przykład
Poniższy przykład rozszerza kierującego biblioteka konwersji, które nie wymagają kontekstu.W tym przykładzie kod konwertuje informacje pracownika z typem macierzystym danych na typ danych zarządzanych.
// 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;
}
W poprzednim przykładzie marshal_as funkcja zwraca uchwyt do przekonwertowanych danych.Zrobiono to w celu zapobieżenia tworzeniu dodatkowych kopii danych.Zwracanie zmiennej bezpośrednio będzie mieć wydajność niepotrzebnych kosztów z nim skojarzony.
Poniższy przykład konwertuje informacje dotyczące pracowników z typu danych zarządzanych rodzimy typ danych.Ta konwersja wymaga kontekstu kierującego.
// 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;
}