Postupy: Rozšíření zařazovací knihovny
Toto téma vysvětluje, jak rozšířit zařazovacího knihovny poskytnout další převody mezi datovými typy. Uživatelé mohou rozšířit zařazovacího knihovny pro všechny převody dat v knihovně není aktuálně podporovaná.
Můžete rozšířit zařazovacího knihovny dvěma způsoby – bez marshal_context Class. Recenze Overview of Marshaling in C++ téma zjistit, zda vyžaduje převod nový kontext.
V obou případech nejprve vytvořit soubor pro nové zařazovací převody. Můžete udělat pro zachování integrity standard kódování soubory knihovny. Pokud chcete projekt do jiného počítače nebo jiného programátor port, musíte zkopírovat nový soubor zařazovacího spolu s ostatními projektu. Uživatel obdrží projektu tímto způsobem zaručit přijímat nové převody a bude třeba upravit soubory knihovny.
Rozšířit knihovnu zařazování převodu, který nevyžaduje kontext
Vytvořte soubor k uložení nové zařazovací funkce, například MyMarshal.h.
Zahrnovat jeden nebo více souborů marshal knihovny:
základní typy Marshal.h.
marshal_windows.h pro typy dat v systému windows.
marshal_cppstd.h pro datové typy STL.
marshal_atl.h pro ATL datové typy.
Pomocí kódu na konci takto napsat funkci převodu. V tomto kódu je převést na typ, od je typ převod z, a from je parametr, který má být převeden.
Nahraďte komentář o logiku převodu kódu pro převod from do objektu na parametr zadejte a vrátí objekt převedený.
namespace msclr {
namespace interop {
template<>
inline TO marshal_as<TO, FROM> (const FROM& from) {
// Insert conversion logic here, and return a TO parameter.
}
}
}
Rozšířit zařazovacího knihovna s převodu, který vyžaduje kontext
Vytvořit soubor k uložení nové zařazovací funkce, například MyMarshal.h.
Zahrnovat jeden nebo více souborů marshal knihovny:
základní typy Marshal.h.
marshal_windows.h pro typy dat v systému windows.
marshal_cppstd.h pro datové typy STL.
marshal_atl.h pro ATL datové typy.
Pomocí kódu na konci takto napsat funkci převodu. Tento kód je převést na typ, je typ převod z, od toObject je ukazatel pro uložení výsledků, a fromObject je parametr, který má být převeden.
Nahraďte komentář o inicializaci s kódem inicializace toPtr vhodné prázdnou hodnotu. Například pokud je ukazatel, nastavte ji na NULL.
Nahraďte komentář o převodu logiky kód převést from parametr do objektu na typu. Tento objekt převedený budou uloženy v toPtr.
Nahraďte komentář o nastavení toObject kódem nastavit toObject převedený objekt.
Nahraďte komentář o čištění nativní kódem bez jakékoli paměti přidělené prostředky toPtr. Pokud toPtr přidělené paměti pomocí new, použijte delete k uvolnění paměti.
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.
}
};
}
}
Příklad
Následující příklad rozšiřuje zařazovacího knihovny pomocí převodu, který nevyžaduje kontext. V tomto příkladu převede kód typu spravované z nativního datového typu informace zaměstnance.
// 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;
}
V předchozím příkladu marshal_as Funkce vrátí popisovač převedená data. Důvodem bylo, aby se předešlo další kopie dat. Vrací proměnnou přímo by mít náklady výkonu zbytečné přidružen.
Následující příklad převede na nativní datový typ informace zaměstnance z spravované datového typu. Tento převod vyžaduje zařazovacího kontext.
// 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;
}