marshal_as<>
久しぶりに #using
どちらかというと、ネイティブとマネージドの互換ルールの記述スタイルをこのような形で用意しましょうというルール付けだったりするわけです。
MSDN2 マーシャリング・ライブラリの拡張
http://msdn.microsoft.com/ja-jp/library/bb531313.aspx
・クラス宣言
struct Natives { std::string PlaceName; double X; double Y; double Z; }; ref class Managed { private: double _x, _y, _z; String^ _placeName; public: Managed() {} void Set(std::string name, double x, double y, double z) { _placeName = marshal_as<String^>(name); this->_x = x; this->_y = y; this->_z = z; } property double X { double get() { return this->_x; } } property double Y { double get() { return this->_y; } } property double Z { double get() { return this->_z; } } property String^ Name { String^ get() { return this->_placeName; } } };
これを相互変換するヘッダを用意するわけです。
・自前の marshal ヘッダ marshal_place.h
namespace msclr { namespace interop { template<> inline Managed^ marshal_as<Managed^, Natives> (const Natives& from) { Managed^ mgd = gcnew Managed; mgd->Set(from.Name, from.X, from.Y, from.Z); return mgd; } template<> ref class context_node<Natives*, Managed^> : public context_node_base { private: Natives* toPtr; public: context_node(Natives*& toObject, Managed^ fromObject) { toPtr = NULL; toPtr = new Native(); toPtr->PlaceName = marshal_as<std::string>(fromObject); toPtr->X = fromObject->X; toPtr->Y = fromObject->Y; toPtr->Z = fromObject->Z; toObject = toPtr; } ~context_node() { this->!context_node(); } protected: !context_node() { if ( toPtr != NULL ) { delete toPtr; toPtr = NULL; } } }; } }
このヘッダを用意しておくと、
#include <marshal_place.h> // struct Natives nat; Managed^ mgt = marshal_as<Managed^>(nat); // Managed^ mgt = gcnew Managed; marshal_context ctx; struct Natives* nat = ctx.marshal_as<Natives*)(mgt);
と言う形で、相互にやりとりできるわけです。
ちょっとした手間ですが、相互やりとりが多い場合にはコードが綺麗になりますね。