Porady: rozszerzanie biblioteki kierowania
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 bibliotekę jakakolwiek konwersja danych nie są obecnie obsługiwane przez biblioteki.
Można rozszerzyć kierującego biblioteki w jeden z dwóch sposobów - z lub bez marshal_context — Klasa.Przegląd Omówienie kierowania w języku C++ tematu, aby ustalić, czy nową konwersję wymaga kontekstu.
W obu przypadkach należy najpierw utworzyć plik dla nowych konwersji dotyczące organizowania.Można to zrobić w celu zachowania spójności standard przekazywania międzyprocesowego plików biblioteki.Jeśli chcesz projektu do innego komputera lub programisty innego portu, należy skopiować nowy plik kierującego wraz z resztą projektu.W ten sposób użytkownik odbiera projektu będzie zagwarantować, aby otrzymać nowe konwersje i nie będą musiały zmodyfikować wszystkie pliki biblioteki.
Aby rozszerzyć kierowanie biblioteki z konwersji, która nie wymaga kontekstu
Tworzenie pliku do przechowywania nowych funkcji kierującego, na przykład MyMarshal.h.
Zawierać co najmniej jeden z plików bibliotek MARSZAŁEK:
Marshal.h dla typów podstawowych.
marshal_windows.h dla typów danych systemu windows.
marshal_cppstd.h dla typów danych STL.
marshal_atl.h dla typów danych biblioteki ATL.
Napisać funkcję konwersji za pomocą kodu na końcu następujące kroki.W niniejszym Kodeksie, to wpisz do konwersji do, FROM jest typ konwersji z, i from jest parametr do konwersji.
Zamień komentarz na temat logiki konwersji na kod do konwersji from parametr na obiekt na typ i Zwraca przekształcony obiekt.
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ć co najmniej jeden z plików bibliotek MARSZAŁEK:
Marshal.h dla typów podstawowych.
marshal_windows.h dla typów danych systemu windows.
marshal_cppstd.h dla typów danych STL.
marshal_atl.h dla typów danych biblioteki ATL.
Napisać funkcję konwersji za pomocą kodu na końcu następujące kroki.W niniejszym Kodeksie, to wpisz do konwersji do, FROM jest typ konwersji z, toObject jest wskaźnikiem do przechowywania wyników, i fromObject jest parametr do konwersji.
Zamień komentarz na temat inicjowanie z kodem zainicjować toPtr na odpowiednią wartość pustą.Na przykład, jeśli jest to wskaźnik, ustaw ją na NULL.
Zamień komentarz na temat logiki konwersji na kod do konwersji from parametr na obiekt z TO typu.Ten obiekt przekonwertowany będą przechowywane w toPtr.
Zamień komentarz na temat ustawienie toObject z kodu, aby ustawić toObject do przekształconego obiektu.
Zamień komentarz na temat czyszczenia macierzystego zasobów z kodu, aby zwolnić wszystkie pamięci przydzielonej 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
W poniższym przykładzie rozszerza kierującego biblioteki z konwersji, która nie wymaga kontekstu.W tym przykładzie kodu konwertuje informacje o pracownikach z rodzimy typ danych do typu 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 przekonwertowane dane.Miało na celu uniemożliwienie tworzenia dodatkowej kopii danych.Zwracanie zmiennej bezpośrednio za opłatą niepotrzebne wydajności związane z nim.
Poniższy przykład konwertuje informacje o pracownikach z typu danych zarządzanych do typu danych w trybie macierzystym.Ta konwersja wymaga kontekstu dotyczące organizowania.
// 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;
}