Nasıl yapılır: Sıralama Kitaplığını Genişletme

Bu konuda, veri türleri arasında daha fazla dönüştürme sağlamak için hazırlama kitaplığının nasıl genişletilmesi açıklanmaktadır. Kullanıcılar, şu anda kitaplık tarafından desteklenmeyen veri dönüştürmeleri için hazırlama kitaplığını genişletebilir.

Sıralama kitaplığını iki yoldan biriyle genişletebilirsiniz: marshal_context Sınıfı ile veya sınıfı olmadan. Yeni bir dönüştürmenin bağlam gerekip gerekmediğini belirlemek için C++ dilinde Hazırlamaya Genel Bakış konusunu gözden geçirin.

Her iki durumda da, önce yeni sıralama dönüştürmeleri için bir dosya oluşturursunuz. Bunu, standart sıralama kitaplığı dosyalarının bütünlüğünü korumak için yaparsınız. Bir projeyi başka bir bilgisayara veya başka bir programcıya taşımayı istiyorsanız, yeni hazırlama dosyasını projenin geri kalanıyla birlikte kopyalamanız gerekir. Bu şekilde, projeyi alan kullanıcının yeni dönüştürmeleri alacağı garanti edilir ve hiçbir kitaplık dosyasını değiştirmesi gerekmez.

Hazırlama Kitaplığını Bağlam Gerektirmeyen Bir Dönüştürme ile Genişletmek için

  1. Yeni sıralama işlevlerini (örneğin, MyMarshal.h) depolamak için bir dosya oluşturun.

  2. Hazırlama kitaplığı dosyalarından birini veya daha fazlasını ekleyin:

    • temel türler için marshal.h.

    • Windows veri türleri için marshal_windows.h.

    • C++ Standart Kitaplığı veri türleri için marshal_cppstd.h.

    • ATL veri türleri için marshal_atl.h.

  3. Dönüştürme işlevini yazmak için bu adımların sonundaki kodu kullanın. Bu kodda, TO dönüştürülecek türdür, FROM dönüştürülecek türdür ve from dönüştürülecek parametredir.

  4. Parametreyi TO türünde bir nesneye dönüştürmek from ve dönüştürülen nesneyi döndürmek için dönüştürme mantığı hakkındaki açıklamayı kodla değiştirin.

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

Hazırlama Kitaplığını Bağlam Gerektiren Bir Dönüştürme ile Genişletmek için

  1. Yeni hazırlama işlevlerini depolamak için bir dosya oluşturun; örneğin, MyMarshal.h

  2. Hazırlama kitaplığı dosyalarından birini veya daha fazlasını ekleyin:

    • temel türler için marshal.h.

    • Windows veri türleri için marshal_windows.h.

    • C++ Standart Kitaplığı veri türleri için marshal_cppstd.h.

    • ATL veri türleri için marshal_atl.h.

  3. Dönüştürme işlevini yazmak için bu adımların sonundaki kodu kullanın. Bu kodda, TO dönüştürülecek türdür, FROM dönüştürülecek türdür, toObject sonucun depolandığı bir işaretçidir ve fromObject dönüştürülecek parametredir.

  4. öğesini uygun boş değere başlatmak toPtr için başlatma hakkındaki açıklamayı kodla değiştirin. Örneğin, işaretçiyse olarak ayarlayın NULL.

  5. Dönüştürme mantığı hakkındaki açıklamayı kodla değiştirerek parametreyi from TO türünde bir nesneye dönüştürün. Dönüştürülen bu nesne içinde toPtrdepolanır.

  6. ayarıyla toObject ilgili açıklamayı dönüştürülen nesnenize ayarlı toObject kodla değiştirin.

  7. tarafından toPtrayrılan belleği boşaltmak için yerel kaynakları temizleme hakkındaki açıklamayı kodla değiştirin. kullanılarak bellek ayrılırsatoPtr, belleği boşaltmak için kullanındelete.new

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

Örnek: Hazırlama kitaplığını genişletme

Aşağıdaki örnek, hazırlama kitaplığını bağlam gerektirmeyen bir dönüştürmeyle genişletir. Bu örnekte kod, çalışan bilgilerini yerel veri türünden yönetilen veri türüne dönüştürür.

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

Önceki örnekte işlev dönüştürülen marshal_as verilere bir tanıtıcı döndürür. Bu, verilerin ek bir kopyasının oluşturulmasını önlemek için yapıldı. Değişkenin doğrudan döndürülmesinde kendisiyle ilişkilendirilmiş gereksiz bir performans maliyeti olacaktır.

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

Örnek: Çalışan bilgilerini dönüştürme

Aşağıdaki örnek, çalışan bilgilerini yönetilen bir veri türünden yerel veri türüne dönüştürür. Bu dönüştürme için bir hazırlama bağlamı gerekir.

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

Ayrıca bkz.

Overview of Marshaling in C++