Compartilhar via


Como: Estender a biblioteca de marshaling

Este tópico explica como estender a biblioteca de marshaling para fornecer mais conversões entre tipos de dados.Os usuários podem estender a biblioteca de marshaling para as conversões de dados não suportadas atualmente da biblioteca.

Você pode estender a biblioteca de marshaling em uma destas duas maneiras - com ou sem um marshal_context Class. Revise o Overview of Marshaling in C++ tópico para determinar se uma nova conversão requer um contexto.

Em ambos os casos, você primeiro criar um arquivo para o novos marshaling conversões.Isso é feito para preservar a integridade do padrão de marshaling de arquivos de biblioteca.Se você desejar um projeto para outro computador ou para outro programador de porta, você deverá copiar o arquivo novo marshaling juntamente com o restante do projeto.Dessa maneira, o usuário receber o projeto vai ser garantido para receber as conversões de novas e não precisará modificar nenhum arquivo de biblioteca.

Para estender a biblioteca de marshaling com uma conversão não requer um contexto

  1. Crie um arquivo para armazenar as novas funções de marshaling, por exemplo, MyMarshal.h.

  2. Incluir um ou mais arquivos da biblioteca de empacotamento:

    • realizar marshaling.h para tipos base.

    • marshal_windows.h para tipos de dados do windows.

    • marshal_cppstd.h para tipos de dados STL.

    • marshal_atl.h ATL tipos de dados.

  3. Use o código no participante destas etapas para escrever a função de conversão.Nesse código, TO é o tipo para converter, FROM é o tipo de conversão do e from é o parâmetro a ser convertido.

  4. substituir comentário sobre a lógica de conversão com código para converter o from parâmetro em um objeto de para digitar e retornar o objeto convertido.

namespace msclr {
   namespace interop {
      template<>
      inline TO marshal_as<TO, FROM> (const FROM& from) {
         // Insert conversion logic here, and return a TO parameter.
      }
   }
}

Para estender a biblioteca de marshaling com uma conversão requer um contexto

  1. Criar um arquivo para armazenar as novas funções de marshaling, por exemplo, MyMarshal.h

  2. Incluir um ou mais arquivos da biblioteca de empacotamento:

    • realizar marshaling.h para tipos base.

    • marshal_windows.h para tipos de dados do windows.

    • marshal_cppstd.h para tipos de dados STL.

    • marshal_atl.h ATL tipos de dados.

  3. Use o código no participante destas etapas para escrever a função de conversão.Nesse código, A é o tipo para converter, FROM é o tipo para converter, toObject é um ponteiro para armazenar o resultado e fromObject é o parâmetro a ser convertido.

  4. substituir comentar inicializar com o código para inicializar o toPtr para o valor apropriado vazio. Por exemplo, se for um ponteiro, defina-lo para NULL.

  5. substituir comentário sobre a lógica de conversão com código para converter o from parâmetro em um objeto de PARA tipo.Este objeto convertido será armazenado no toPtr.

  6. substituir comentário sobre a configuração de toObject com o código para conjunto toObject para o objeto convertido.

  7. Substitua o comentário sobre limpeza de recursos nativo com o código para disponível qualquer memória alocada por toPtr. If toPtr memória alocada, usando new, use delete Para liberar a memória.

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.
         }
      };
   }
} 

Exemplo

O exemplo a seguir amplia a biblioteca de marshaling com uma conversão que não requer um contexto.Neste exemplo, o código converte as informações do funcionário de um tipo de dados nativo para um dados gerenciados tipo.

// 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;
}

No exemplo anterior, a marshal_as função retorna um identificador de dados convertidos. Isso foi concluído para evitar criar uma cópia adicional dos dados.Retornando a variável diretamente seria ter um custo de desempenho desnecessária associado a ele.

Managed name: Jeff Smith Managed address: 123 Main Street Managed zip code: 98111

O exemplo a seguir converte as informações do funcionário de um tipo de dados gerenciado em um tipo de dados nativo.Esta conversão requer um contexto de marshaling.

// 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

Consulte também

Conceitos

Overview of Marshaling in C++