
- 軜éHTTPãµãŒãã¹ã®éçº
- ããã»ã¹éã§è»¢éãããã€ã³ã¿ãŒãã§ãŒã¹ãä»ãããã€ã¯ããµãŒãã¹éä¿¡
- ããŸããŸãªåœ¢åŒã®ããŒã¿æ§é ã®åæ ã«åºã¥ãã·ãªã¢ã«åãšéã·ãªã¢ã«å
- ããŒã¿ããŒã¹ãæäœãã
- ãµãŒãã¹ã¯ã€ã€ãã¬ãŒã ãäœæããããã®ããã€ãã®ãã«ããŒã³ã³ããŒãã³ã
ãããã¯ãã¹ãŠãWebçšã®ããã¯ãšã³ããµãŒãã¹ã®éçºã«çŠç¹ãåœãŠãŠããŸãããä»ã®ã·ã¹ãã ã§ã䜿çšã§ããŸãã
ã¯ããã«
æ°ããC ++æšæºã®ãªãªãŒã¹ã次ã®æºåã 幎ãçµã¡ãŸãããC ++ã«ã¯åæ ããããŸããã C ++ã§ã®ãªãã¬ã¯ã·ã§ã³ã®åºçŸã®å¯èœæ§ãè°è«ããã次ã®æšæºã«å«ãŸããããã«æãããŸããã ããã...ãã¶ãåå°ã¯å¿ èŠãããŸãããïŒ ãã¶ã...ããããããã圹ç«ã€å¯èœæ§ã®ããã¿ã¹ã¯ããããŸãïŒããã»ã¹ééä¿¡ïŒIPCãRPCãREST APIããã€ã¯ããµãŒãã¹ïŒãããŒã¿ããŒã¹ïŒORMïŒã®æäœãããŸããŸãªïŒdeïŒã·ãªã¢ã©ã€ã¶ãŒãªã©ã -äžè¬çã«ãç³è«ã®äœå°ããããŸãã
ã³ã³ãã€ã©ã«ã¯ãã¹ãŠã®åæ å ±ããããéçºè ãšå ±æããŠã¿ãŸãããïŒ ç§ã¯ãã³ã³ãã€ã©éçºè ããã®æ å ±ãä»ã®ãœãããŠã§ã¢ã®æ£çŽãªéçºè ã«å ¬éãã¹ãææžãåã«ååšããªããšä»®å®ããããšããŸãã ãã®ãããªããã¥ã¡ã³ãã¯C ++æšæºã§ããããããŒãã£ã³ãã€ãžã³ã°ãèŠå¶ã¯äžåãããŸããã
å€ãã®èšèªã«ã¯ãªãã¬ã¯ã·ã§ã³ããããŸãã C ++ã¯ãçç£æ§ãéèŠãªããã°ã©ã ãéçºããããã®èšèªãšèããããŠãããã¢ããªã±ãŒã·ã§ã³ã®åéã®1ã€ã¯Webéçºã§ãã ããã¯ãšã³ããµãŒãã¹ã®éçºã ãã®æ¥çã«ã¯ãREST APIãORMãããã³ãããããã®ãžã®ããããçš®é¡ã®ã·ãªã¢ã«åããããŸãïŒå€ãã®å Žåjsonã§ïŒã ãããã®åé¡ã解決ããã«ã¯ãæ¢è£œã®ã©ã€ãã©ãªã䜿çšããããç¬èªã®ã©ã€ãã©ãªãäœæããå¿ èŠããããŸããC++ããŒã¿ã¯ãC ++ã®æ§é ãjson圢åŒã«ãããã³ã°ãããªã©ãä»ã®ãšã³ãã£ãã£ãšæåã§æ¥ç¶ããŸãã ãã¯ãã®å©ããåããŠãã¿ã€ãã«é¢ããã¡ã¿æ å ±ãè¿œå ãããããšããããŸããããã¯ãåŸã§REST APIãORMãªã©ã®æ§ç¯ã§äœ¿çšãããŸãã odbãªã©ãã³ã³ãã€ã©çšã®ãã©ã°ã€ã³ã䜿çšãããœãªã¥ãŒã·ã§ã³ããããŸãã
å€éšãŠãŒãã£ãªãã£ã«ããã³ãŒãçæããã¯ããšãã³ãã¬ãŒãã®ç©ã¿éãããŸãã¯æåã®ããããã³ã°ããªãã§ããã£ãšèªç¶ãªãã®ã«ããããšæããŸãã ããã¯ãŸã å©çšã§ããŸããããããã®åé¡ã解決ããã«ã¯ãäžèšã®ã¢ãããŒãã®ãããããéžæããå¿ èŠããããŸãã
ææ¡ããããœãªã¥ãŒã·ã§ã³ã¯ãC ++åã«ã¡ã¿æ å ±ãè¿œå ãããã®åŸããŸããŸãªåé¡ã解決ããéã«äœ¿çšããããšã«åºã¥ããŠããŸãã ãã¿ã€ãã¯åœŒã«é¢ããã¡ã¿æ å ±ã§ã©ããããå¿ èŠããããŸãããšèšãããšãã§ããŸãããã®åŸã圌ã¯ããã»ã¹ãšããŒã¿ã»ã³ã¿ãŒã®å¢çã倧èã«æ©ããæå°éã®éçºè ã®ä»å ¥ã§ããŸããŸãªæ¹æ³ïŒãã€ããªãjsonãxmlãããã¹ããªã©ïŒã§èªåèªèº«ãæ瀺ã§ããŸãã
å€ãã®å Žåããã®ãããªã¿ã¹ã¯ã¯ãã³ãŒãçæãããšãã°thrift ã gSOAP ã protobufãªã©ã䜿çšããŠè§£æ±ºãããŸãã å€éšã³ãŒãçæãé€å€ããç¬èªã®ãœãªã¥ãŒã·ã§ã³ãååŸãããã£ããããå¿ èŠãªãã®ã¯ãã¹ãŠã³ã³ãã€ã«æã«åã«è¿œå ããããšåæã«ãæ¢åã®èšèªã§æ°ããèšèªãäœæããã«ãC ++èšèªã®èªç¶ãªæ§æãå¯èœãªéãä¿æãããã®ã§ãã
äŸã®MIF
MIFãããžã§ã¯ãã®ããã€ãã®æ©èœã玹ä»ããããšæããŸãã æçš¿ãžã®ãã£ãŒãããã¯ã§ã¯ãããããããã®ãœãªã¥ãŒã·ã§ã³ãŸãã¯ãã®ãœãªã¥ãŒã·ã§ã³ãéžã°ããçç±ã®ãã¹ãŠã®ããªãã¯ã埮åŠããããã³èª¬æãå«ãå®è£ ã«é¢ããæçš¿ãæºåããŸãã
æçš¿ã®åé ã«ãªã¹ããããŠããã¿ã¹ã¯ã¯ãã·ãªã¢ã«åããªããžã§ã¯ãæåã®ããã»ã¹ééä¿¡ãREST APIå®è£ ãªã©ã®C ++ããŒã¿åã衚瀺ããæ©äŒãããããšã瀺åããŠããŸãã ããã§ç§ã¯ææ¡ããŠéå§ããŸã...
åå°
ãªãã¬ã¯ã·ã§ã³ã¯ãããžã§ã¯ãå šäœã®åºç€ã§ãããããã«ãããé©çšãããåé¡ã解決ã§ããŸãã
C ++ããŒã¿æ§é ã®ååããã®ãã£ãŒã«ãã®æ°ãååŸãããã®çªå·ã§ãã£ãŒã«ãã®1ã€ã«ã¢ã¯ã»ã¹ããæ¹æ³ã®äŸã
struct Data { int field1 = 0; std::string field2; };
åé¡ã®è§£æ±ºçã¯æ¬¡ã®ããã«ãªããŸãã
int main() { Data data; data.field1 = 100500; data.field2 = "Text"; using Meta = Mif::Reflection::Reflect<Data>; std::cout << "Struct name: " << Meta::Name::GetString() << std::endl; std::cout << "Field count: " << Meta::Fields::Count << std::endl; std::cout << "Field1 value: " << data.field1 << std::endl; std::cout << "Field2 value: " << data.field2 << std::endl; std::cout << "Modify fields." << std::endl; data.*Meta::Fields::Field<0>::Access() = 500100; data.*Meta::Fields::Field<1>::Access() = "New Text."; std::cout << "Field1 value: " << data.field1 << std::endl; std::cout << "Field2 value: " << data.field2 << std::endl; return 0; }
ãã¹ãŠããã®ããã«ãªã£ãŠããã¯ãã§ããå°ãç°ãªã£ãŠæžãããŠããŸããããã®æšæºã§ã¯C ++ããŒã¿åãããã»ã©ç°¡åã«è¡šç€ºããããšã¯ã§ããŸããã ãããŠãæå®ãããã³ãŒããæ©èœãããã«ã¯ãã¡ã¿æ å ±ãããŒã¿æ§é ã«è¿œå ããå¿ èŠããããŸã
MIF_REFLECT_BEGIN(Data) MIF_REFLECT_FIELD(field1) MIF_REFLECT_FIELD(field2) MIF_REFLECT_END() MIF_REGISTER_REFLECTED_TYPE(Data)
åã®ã¡ã¿æ å ±ãåèªäœã«è¿œå ããŠãæ¡åŒµã§ããŸãã ã³ãŒããšã®å¹²æžãäžå¯èœãªã¿ã€ãïŒãµãŒãããŒãã£ã©ã€ãã©ãªã®ã¿ã€ãïŒã衚瀺ã§ããããã«ããããã«ããã®ãããªæ±ºå®ãæåŠããããšæããŸãã ããã€ãã®ãã¯ãã䜿çšãããšãä»åŸã®äœæ¥ã«å¿ èŠãªãã¹ãŠã®æ å ±ãè¿œå ã§ããŸãã ç¶æ¿ã®å¯èœæ§ããããŸãããããã«ã€ããŠã¯åŸã§è©³ãã説æããŸã...
å®å
šãªãµã³ãã«ã³ãŒã
// STD #include <iostream> #include <string> // MIF #include <mif/reflection/reflect_type.h> #include <mif/reflection/reflection.h> struct Data { int field1 = 0; std::string field2; }; MIF_REFLECT_BEGIN(Data) MIF_REFLECT_FIELD(field1) MIF_REFLECT_FIELD(field2) MIF_REFLECT_END() MIF_REGISTER_REFLECTED_TYPE(Data) int main() { Data data; data.field1 = 100500; data.field2 = "Text"; using Meta = Mif::Reflection::Reflect<Data>; std::cout << "Struct name: " << Meta::Name::GetString() << std::endl; std::cout << "Field count: " << Meta::Fields::Count << std::endl; std::cout << "Field1 value: " << data.field1 << std::endl; std::cout << "Field2 value: " << data.field2 << std::endl; std::cout << "Modify fields." << std::endl; data.*Meta::Fields::Field<0>::Access() = 500100; data.*Meta::Fields::Field<1>::Access() = "New Text."; std::cout << "Field1 value: " << data.field1 << std::endl; std::cout << "Field2 value: " << data.field2 << std::endl; return 0; }
å°ãè€éãªäŸïŒæ§é ãšãã®åºæ¬æ§é ã®ãã¹ãŠã®ãã£ãŒã«ãã®ã³ã³ãœãŒã«ã«äžè¬åãããåºåã³ãŒããæžã蟌ãããšããŸãã
æ§é ãŠã©ãŒã¯ã®äŸ
// STD #include <iostream> #include <map> #include <string> #include <type_traits> // MIF #include <mif/reflection/reflect_type.h> #include <mif/reflection/reflection.h> #include <mif/serialization/traits.h> struct Base1 { int field1 = 0; bool field2 = false; }; struct Base2 { std::string field3; }; struct Nested { int field = 0; }; struct Data : Base1, Base2 { int field4 = 0; std::string field5; std::map<std::string, Nested> field6; }; MIF_REFLECT_BEGIN(Base1) MIF_REFLECT_FIELD(field1) MIF_REFLECT_FIELD(field2) MIF_REFLECT_END() MIF_REFLECT_BEGIN(Base2) MIF_REFLECT_FIELD(field3) MIF_REFLECT_END() MIF_REFLECT_BEGIN(Nested) MIF_REFLECT_FIELD(field) MIF_REFLECT_END() MIF_REFLECT_BEGIN(Data, Base1, Base2) MIF_REFLECT_FIELD(field4) MIF_REFLECT_FIELD(field5) MIF_REFLECT_FIELD(field6) MIF_REFLECT_END() MIF_REGISTER_REFLECTED_TYPE(Base1) MIF_REGISTER_REFLECTED_TYPE(Base2) MIF_REGISTER_REFLECTED_TYPE(Nested) MIF_REGISTER_REFLECTED_TYPE(Data) class Printer final { public: template <typename T> static typename std::enable_if<Mif::Reflection::IsReflectable<T>(), void>::type Print(T const &data) { using Meta = Mif::Reflection::Reflect<T>; using Base = typename Meta::Base; PrintBase<0, std::tuple_size<Base>::value, Base>(data); std::cout << "Struct name: " << Meta::Name::GetString() << std::endl; Print<0, Meta::Fields::Count>(data); } template <typename T> static typename std::enable_if < !Mif::Reflection::IsReflectable<T>() && !Mif::Serialization::Traits::IsIterable<T>(), void >::type Print(T const &data) { std::cout << data << std::boolalpha << std::endl; } template <typename T> static typename std::enable_if < !Mif::Reflection::IsReflectable<T>() && Mif::Serialization::Traits::IsIterable<T>(), void >::type Print(T const &data) { for (auto const &i : data) Print(i); } private: template <std::size_t I, std::size_t N, typename T> static typename std::enable_if<I != N, void>::type Print(T const &data) { using Meta = Mif::Reflection::Reflect<T>; using Field = typename Meta::Fields::template Field<I>; std::cout << Field::Name::GetString() << " = "; Print(data.*Field::Access()); Print<I + 1, N>(data); } template <std::size_t I, std::size_t N, typename T> static typename std::enable_if<I == N, void>::type Print(T const &) { } template <typename K, typename V> static void Print(std::pair<K, V> const &p) { Print(p.first); Print(p.second); } template <std::size_t I, std::size_t N, typename B, typename T> static typename std::enable_if<I != N, void>::type PrintBase(T const &data) { using Type = typename std::tuple_element<I, B>::type; Print(static_cast<Type const &>(data)); PrintBase<I + 1, N, B>(data); } template <std::size_t I, std::size_t N, typename B, typename T> static typename std::enable_if<I == N, void>::type PrintBase(T const &) { } }; int main() { Data data; data.field1 = 1; data.field2 = true; data.field3 = "Text"; data.field4 = 100; data.field5 = "String"; data.field6["key1"].field = 100; data.field6["key2"].field = 200; Printer::Print(data); return 0; }
çµæ
Struct name: Base1 field1 = 1 field2 = true Struct name: Base2 field3 = Text Struct name: Data field4 = 100 field5 = String field6 = key1 Struct name: Nested field = 100 key2 Struct name: Nested field = 200
äŸã¯ãå®å šãªã·ãªã¢ã©ã€ã¶ãŒã®ãããã¿ã€ãã§ãã è¿œå ãããã¡ã¿æ å ±ã«åºã¥ããŠãæ§é ãã¹ããªãŒã ïŒãã®äŸã§ã¯æšæºåºåã¹ããªãŒã ïŒã«ã·ãªã¢ã«åããŸãã åãã³ã³ãããã©ãããå€æããã«ã¯ãSerializationåå空éã®é¢æ°ã䜿çšãããŸãã ãã®åå空éã«ã¯ãjsonããã³boost.archivesïŒxmlãtextãbinaryïŒã®æ¢è£œã®ã·ãªã¢ã©ã€ã¶ãŒãå«ãŸããŠããŸãã ãããã¯ãäŸã§ç€ºãããã®ã«è¿ãååã«åºã¥ããŠæ§ç¯ãããŠããŸãã ã·ãªã¢ã©ã€ã¶ãŒã§ãã¬ãŒã ã¯ãŒã¯ãæ¡åŒµããå¿ èŠããªãå Žåããã®ãããªã³ãŒããèšè¿°ããå¿ èŠã¯ãããŸããã
Printerã¯ã©ã¹ã䜿çšãã代ããã«ãjsonãªã©ã§æ¢è£œã®ã·ãªã¢ã©ã€ã¶ãŒã䜿çšã§ããŸããããã«ãããã³ãŒãã®éãå€§å¹ ã«åæžãããŸãã
#include <mif/reflection/reflect_type.h> #include <mif/serialization/json.h> // Data and meta int main() { Data data; // Fill data auto const buffer = Mif::Serialization::Json::Serialize(data); // json std::cout << buffer.data() << std::endl; return 0; }
äœæ¥çµæ
{ "Base1" : { "field1" : 1, "field2" : true }, "Base2" : { "field3" : "Text" }, "field4" : 100, "field5" : "String", "field6" : [ { "id" : "key1", "val" : { "field" : 100 } }, { "id" : "key2", "val" : { "field" : 200 } } ] }
å€æŽã«ã€ããŠã¯ãboost.archivesã®ã·ãªã¢ã«åãxml圢åŒã§äœ¿çšããŠã¿ãŠãã ããã
boost.archivesã䜿çšããXMLã§ã®ã·ãªã¢ã«å
// BOOST #include <boost/archive/xml_oarchive.hpp> // MIF #include <mif/reflection/reflect_type.h> #include <mif/serialization/boost.h> // Data and meta int main() { Data data; // Fill data boost::archive::xml_oarchive archive{std::cout}; archive << boost::serialization::make_nvp("data", data); return 0; }
äœæ¥çµæ
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?> <!DOCTYPE boost_serialization> <boost_serialization signature="serialization::archive" version="14"> <data class_id="0" tracking_level="0" version="0"> <Base1 class_id="1" tracking_level="0" version="0"> <field1>1</field1> <field2>1</field2> </Base1> <Base2 class_id="2" tracking_level="0" version="0"> <field3>Text</field3> </Base2> <field4>100</field4> <field5>String</field5> <field6 class_id="3" tracking_level="0" version="0"> <count>2</count> <item_version>0</item_version> <item class_id="4" tracking_level="0" version="0"> <first>key1</first> <second class_id="5" tracking_level="0" version="0"> <field>100</field> </second> </item> <item> <first>key2</first> <second> <field>200</field> </second> </item> </field6> </data> </boost_serialization>
ãã®äŸãããããããã«ãç¹å®ã®ã·ãªã¢ã©ã€ã¶ãŒãåŒã³åºã以å€ã¯äœãå€ãããŸããã åãã¡ã¿æ å ±ã䜿çšãããŸãã ãŸããããã»ã¹ééä¿¡ãå®è£ ãããšãã«ä»ã®å Žæã§äœ¿çšãããŸãã
ããã€ãã®åœ¢åŒã®ã·ãªã¢ã©ã€ãŒãŒã·ã§ã³ãšãã·ãªã¢ã©ã€ã¶ããã¬ãŒã ã¯ãŒã¯ã«å®è£ ãããŠããŸãã ãŸããå¿ èŠã«å¿ããŠãPrinterã¯ã©ã¹ã®äŸã䜿çšããããææ¡ãããAPIã䜿çšããŠj ++圢åŒã®ïŒdeïŒã·ãªã¢ã©ã€ã¶ãŒã䜿çšããŠC ++ããŒã¿æ§é ããã€ãã¹ããããšã«ãããæ°ãã圢åŒã®ãµããŒããè¿œå ã§ããŸãã åã«ã¯ããã€ãã®å¶éããããŸãïŒãããããªãå ŽåïŒããããã«ã€ããŠã¯åŸã§è©³ãã説æããŸãã
ããã«ãããèå³æ·±ããã®ã«é²ãããšãææ¡ããŸã-ããã»ã¹éã§è»¢éãããã€ã³ã¿ãŒãã§ãŒã¹ã«åºã¥ããŠããã»ã¹ééä¿¡ãå®è£ ããŸãïŒçŽç²ãªä»®æ³ã¡ãœããã䜿çšããC ++ããŒã¿æ§é ïŒã
ããã»ã¹ééä¿¡
MIFãããžã§ã¯ããå§ãŸã£ãã®ã¯ãããã»ã¹ééä¿¡ã®å®è£ ã§ãã ããã¯åªå äºé ã§ããã ãã®ã¡ã«ããºã ã®æåã®å®è£ ã®1ã€ã§ããµãŒãã¹ã®1ã€ãéçºãããŸããããã®ãµãŒãã¹ã®å·çæç¹ã§ã¯ããããã®è¡ã¯ã¯ã©ãã·ã¥ããªããŒããªãã§6ãæ以äžå®å®ããŠæ©èœããŠããŸããã
ã€ã³ã¿ãŒãã§ã€ã¹ã䜿çšããŠãè€æ°ã®ãã·ã³äžã«ãããµãŒãã¹ã®éä¿¡ãè¡ãå¿ èŠããããŸããã ãŸãã§ãã¹ãŠã1ã€ã®ããã»ã¹ã«ãããã®ããã«ããµãŒãã¹ãæäœãããã£ãã®ã§ãã
äŸã§ã¯ãç®çã®çµæã«ã©ãã ãè¿ã¥ãããã瀺ããŠããŸãã
ç®çïŒæ¶ç©ºã®äŒç€Ÿã®åŸæ¥å¡ã«é¢ããæ å ±ã亀æããããã®ãµãŒããŒãšã¯ã©ã€ã¢ã³ããéçºããã
ãã®ãããªåé¡ã®è§£æ±ºçã¯ãããã€ãã®åæ§ã®ã¹ãããã«åæžãããŸã
- ã³ã³ããŒãã³ãã€ã³ã¿ãŒãã§ã€ã¹ãå®çŸ©ãã
- ã¡ãœãããã©ã¡ãŒã¿ã®æ»ãå€ãšããŠãã«ã¹ã¿ã ããŒã¿æ§é ãå®çŸ©ããïŒå¿ èŠãªå ŽåïŒ
- ã¡ã¿æ å ±ãè¿œå ãã
- ãµãŒããŒã¢ããªã±ãŒã·ã§ã³ãå®è£ ãã
- ã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ãå®è£ ãã
Complex_typeã®äŸ
äžè¬éš
ããŒã¿æ§é
// data.h namespace Service { namespace Data { using ID = std::string; struct Human { std::string name; std::string lastName; std::uint32_t age = 0; }; enum class Position { Unknown, Developer, Manager }; struct Employee : public Human { Position position = Position::Unknown; }; using Employees = std::map<ID, Employee>; } // namespace Data } // namespace Service
ã¡ã¿æ å ±
// meta/data.h namespace Service { namespace Data { namespace Meta { using namespace ::Service::Data; MIF_REFLECT_BEGIN(Human) MIF_REFLECT_FIELD(name) MIF_REFLECT_FIELD(lastName) MIF_REFLECT_FIELD(age) MIF_REFLECT_END() MIF_REFLECT_BEGIN(Position) MIF_REFLECT_FIELD(Unknown) MIF_REFLECT_FIELD(Developer) MIF_REFLECT_FIELD(Manager) MIF_REFLECT_END() MIF_REFLECT_BEGIN(Employee, Human) MIF_REFLECT_FIELD(position) MIF_REFLECT_END() } // namespace Meta } // namespace Data } // namespace Service MIF_REGISTER_REFLECTED_TYPE(::Service::Data::Meta::Human) MIF_REGISTER_REFLECTED_TYPE(::Service::Data::Meta::Position) MIF_REGISTER_REFLECTED_TYPE(::Service::Data::Meta::Employee)
ã€ã³ã¿ãŒãã§ãŒã¹
// imy_company.h namespace Service { struct IMyCompany : public Mif::Service::Inherit<Mif::Service::IService> { virtual Data::ID AddEmployee(Data::Employee const &employee) = 0; virtual void RemoveAccount(Data::ID const &id) = 0; virtual Data::Employees GetEmployees() const = 0; }; } // namespace Service
ã¡ã¿æ å ±
// ps/imy_company.h namespace Service { namespace Meta { using namespace ::Service; MIF_REMOTE_PS_BEGIN(IMyCompany) MIF_REMOTE_METHOD(AddEmployee) MIF_REMOTE_METHOD(RemoveAccount) MIF_REMOTE_METHOD(GetEmployees) MIF_REMOTE_PS_END() } // namespace Meta } // namespace Service MIF_REMOTE_REGISTER_PS(Service::Meta::IMyCompany)
ããŒã¿æ§é ã®å®çŸ©ãšã¡ã¿æ å ±ã®è¿œå ã¯ããã¹ãŠãåå空éã§åºåãããŠããããšãé€ããŠããªãã¬ã¯ã·ã§ã³ã䜿çšããäŸãšåãã§ãã
ã€ã³ã¿ãŒãã§ã€ã¹å®çŸ©ã¯ãçŽç²ãªä»®æ³ã¡ãœããã®ã¿ãå«ãããŒã¿æ§é ã®C ++å®çŸ©ã§ãã
ã€ã³ã¿ãŒãã§ãŒã¹ã«ã€ããŠã¯ãå¥ã®èŠæããããŸãããããã€ã³ã¿ãŒãã§ãŒã¹ãããå®è£ ã«å«ãŸããä»ã®ã€ã³ã¿ãŒãã§ãŒã¹ã«ãªã¯ãšã¹ãããæ©èœã§ãããåäžã®éå±€ã«æ¥ç¶ãããŠããªãå¯èœæ§ããããŸãã ãããã£ãŠãå®çŸ©ãããã€ã³ã¿ãŒãã§ã€ã¹ã¯ãåžžã«Mif :: Service :: IServiceãŸãã¯Mif :: Service :: IServiceãç¶æ¿ããä»ã®ã€ã³ã¿ãŒãã§ã€ã¹ãç¶æ¿ããå¿ èŠããããŸãã å€éç¶æ¿ããããŸãã ç¶æ¿ã¯ãäžéãšã³ãã£ãã£Mif :: Service :: Inheritãä»ããŠè¡ãããŸãã ããã¯ãå¯å€æ°ã®ãã©ã¡ãŒã¿ãŒãæã€ãã³ãã¬ãŒãã§ãã ãã®ãã©ã¡ãŒã¿ãŒã¯ãç¶æ¿ãããã€ã³ã¿ãŒãã§ãŒã¹ãŸãã¯å®è£ ã§ãïŒ ç¶æ¿ ïŒã ããã¯ãdynamic_castãšåãã§ãããããã»ã¹ã®å€éšã§åäœããã€ã³ã¿ãŒãã§ã€ã¹ãèŠæ±ããã¡ã«ããºã ãå®è£ ããããã«å¿ èŠã§ãã
ã€ã³ã¿ãŒãã§ã€ã¹ã«ã¡ã¿æ å ±ãè¿œå ããããšã¯ãããŒã¿æ§é ã«ã¡ã¿æ å ±ãè¿œå ããããšãšç¹ã«éãã¯ãããŸããã ããã¯ãç°ãªããé¡äŒŒãããã¯ãã®ã»ããã§ãã ãã ããããããåŸã§ãããŒã¿æ§é ãšã€ã³ã¿ãŒãã§ã€ã¹ãå®çŸ©ããããã®ãã¹ãŠãåäžã®ãã¯ãã»ããã«çž®å°ãããŸãã éããŸããã ããã¯ããããžã§ã¯ãã®éçºäžã«çºçããŸããã
ã€ã³ã¿ãŒãã§ã€ã¹ã«ã¡ã¿æ å ±ãè¿œå ããå Žåããã®åºæ¬çãªã€ã³ã¿ãŒãã§ã€ã¹ã¯å¿ èŠãããŸããã éå±€å šäœã¯ã³ã³ãã€ã«æã«æ€åºãããŸãã ããã§ãå°ããªè£å©ãšã³ãã£ãã£Mif :: Service :: Inheritã¯ãçžç¶äººããã³é¢é£ããã¡ã¿æ å ±ã®æ€çŽ¢ã§äž»ãªåœ¹å²ãæãããŸãã
ã¡ã¿æ å ±ãã€ã³ã¿ãŒãã§ãŒã¹ã«è¿œå ããå Žåããã©ã¡ãŒã¿ãŒãæ»ãå€ãããã³cv修食åãæå®ããã«ãã€ã³ã¿ãŒãã§ãŒã¹ãšãã®ã¡ãœããã®ã¿ãæå®ãããŸãã ããããªãºã ã®ç²Ÿç¥ã§ãã€ã³ã¿ãŒãã§ãŒã¹ã«ã¡ã¿æ å ±ãè¿œå ããããšããèŠæããããŸããã éè² è·ã®æ¬ åŠãããããªãºã ã®ä»£äŸ¡ã«ãªããŸããã ããã¯ããã¹ãŠã®ãã©ã¡ãŒã¿ãŒãäžèŠ§è¡šç€ºãããåã¡ãœããã®å€ã®åãè¿ãããã€ã³ã¿ãŒãã§ã€ã¹ãå°ãå€æŽããã ãã§ç·šéã§ããªããããäœäŸ¡æ Œã ãšèããŠããŸãã
å ±éã®ãšã³ãã£ãã£ãå®çŸ©ãããããµãŒããŒããã³ã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ãå®è£ ããŸãã
åã€ã³ã¿ãŒãã§ã€ã¹ã«ã¯å€ãã®å®è£ ããããŸãã 圌ãã¯äœããã®åœ¢ã§åºå¥ãããå¿ èŠããããŸãã ãªããžã§ã¯ããäœæãããšããç®çã®å®è£ ãæ瀺çã«æå®ããå¿ èŠããããŸãã ãã®ããã«ã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã®å®è£ ã®èå¥åãšå®è£ ãšã®æ¥ç¶ãå¿ èŠã§ãã
ãã³ãŒãå ã®éæ³ã®å€ãã䟿å©ã«æåŠããããã«ãå®è£ èå¥åã¯1ã€ä»¥äžã®ããããŒãã¡ã€ã«ã«é 眮ããæ¹ãé©åã§ãã MIFãããžã§ã¯ãã§ã¯ãçªå·ãèå¥åãšããŠäœ¿çšãããŸãã äœããã®æ¹æ³ã§ã«ãŠã³ã¿ãæ°ãããããã¹ãŠãåäžã®åæã«å ¥ãããããã«äžæã«ããããèå¥åãç°ãªããã¡ã€ã«ãåå空éã«è«ççã«åé¢ã§ããããã«ããããã«ãäžæã«ããã«ã¯ãæååããcrc32ãèå¥åãšããŠäœ¿çšããããšããå§ãããŸãéçºè ã®æ¹ãå°ãªãã¯ãã§ãã
IMyCompanyãå®è£ ããã«ã¯èå¥åãå¿ èŠã§ã
// id/service.h namespace Service { namespace Id { enum { MyCompany = Mif::Common::Crc32("MyCompany") }; } // namespace Id } // namespace Service
ãµãŒããŒã¢ããªã±ãŒã·ã§ã³
IMyCompanyã®å®è£
// service.cpp // MIF #include <mif/common/log.h> #include <mif/reflection/reflection.h> #include <mif/service/creator.h> // COMMON #include "common/id/service.h" #include "common/interface/imy_company.h" #include "common/meta/data.h" namespace Service { namespace Detail { namespace { class MyCompany : public Mif::Service::Inherit<IMyCompany> { public: // ⊠private: // ⊠// IMyCompany virtual Data::ID AddEmployee(Data::Employee const &employee) override final { // ... } virtual void RemoveAccount(Data::ID const &id) override final { // ... } } virtual Data::Employees GetEmployees() const override final { // ... } }; } // namespace } // namespace Detail } // namespace Service MIF_SERVICE_CREATOR ( ::Service::Id::MyCompany, ::Service::Detail::MyCompany )
泚ç®ãããç¹ãããã€ããããŸãã
- å®è£ ã®ç¶æ¿ããMif :: Service :: Inheritãä»ããŠè¡ãããŸãã ããã¯å¿ é ã§ã¯ãããŸããããé©åãªåœ¢åŒãšèŠãªãããšãã§ãã以åã«å®è£ ãããããã€ãã®ã€ã³ã¿ãŒãã§ã€ã¹ãç¶æ¿ããŠããã€ãã®ã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããå Žåã«åœ¹ç«ã¡ãŸãã
- å®è£ å šäœã¯ãhãã¡ã€ã«ãšcppãã¡ã€ã«ã«åå²ããããšãªãã1ã€ã®cppãã¡ã€ã«ã§å®è¡ã§ããŸãã ããã«ãããå¿ èŠãªãã¹ãŠã®ã€ã³ã¯ã«ãŒãå®è£ ãã¡ã€ã«ãå®è£ ãã¡ã€ã«ã«å«ãŸããŠãããããã«ãã»ã«åã匷åãããã倧èŠæš¡ãããžã§ã¯ãã§ã³ã³ãã€ã«æéãççž®ãããã§ããŸãã å€æŽããããšãåã³ã³ãã€ã«ãããäŸåcppãã¡ã€ã«ã®æ°ãå°ãªããªããŸãã
- åå®è£ ã«ã¯ãšã³ããªãã€ã³ãããããŸã-MIF_SERVICE_CREATORã¯å®è£ ãã¡ã¯ããªã§ãã ãã©ã¡ãŒã¿ãŒã¯ãå®è£ ã¯ã©ã¹ãèå¥åãããã³å¿ èŠã«å¿ããŠå®è£ ã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ãããå¯å€æ°ã®ãã©ã¡ãŒã¿ãŒã§ãã
ãµãŒããŒã¢ããªã±ãŒã·ã§ã³ãå®æãããããã«ãã¡ã€ã³ãã€ã³ãã§ãããšã³ããªãã€ã³ããè¿œå ããŸãã
// MIF #include <mif/application/tcp_service.h> // COMMON #include "common/id/service.h" #include "common/ps/imy_company.h" class Application : public Mif::Application::TcpService { public: using TcpService::TcpService; private: // Mif.Application.Application virtual void Init(Mif::Service::FactoryPtr factory) override final { factory->AddClass<::Service::Id::MyCompany>(); } }; int main(int argc, char const **argv) { return Mif::Application::Run<Application>(argc, argv); }
ãšã³ããªãã€ã³ããäœæããå Žåãã¢ããªã±ãŒã·ã§ã³ã¯ã©ã¹ãå®è£ ããå¿ èŠããããŸããããã¯ãåºæ¬ã¢ããªã±ãŒã·ã§ã³ã¯ã©ã¹ãŸãã¯äºåå®çŸ©ãããã¢ããªã±ãŒã·ã§ã³ãã³ãã¬ãŒãã®ããããã®ç¶æ¿è ã§ãã åå®çŸ©ãããInitã¡ãœããã§ã¯ããµãŒãã¹ããšã¯ã¹ããŒãããã€ã³ã¿ãŒãã§ãŒã¹ã®ãã¹ãŠã®æ¢åã®å®è£ ããã¡ã¯ããªãŒã«è¿œå ããå¿ èŠããããŸãïŒfactory-> AddClassïŒã å®è£ ã³ã³ã¹ãã©ã¯ã¿ãŒã®ãã©ã¡ãŒã¿ãŒãAddClassã¡ãœããã«æž¡ãããšãã§ããŸãã
ãã®ãµãŒãã¹ã¯ãgzipå§çž®ã䜿çšãããã€ããªåœ¢åŒã®boost.archiveã«åºã¥ãå®çŸ©æžã¿ã®ãã©ã³ã¹ããŒãtcpãã·ãªã¢ã«åã䜿çšããŠãã€ã³ã¿ãŒãã§ã€ã¹ãã¡ãœããããã©ã¡ãŒã¿ãŒãè¿ãããçµæãäŸå€ãããã³ãªããžã§ã¯ãã€ã³ã¹ã¿ã³ã¹ã«é¢ããæ å ±ã亀æããŸãã
å¥ã®ã¿ã€ãã®ãã©ã³ã¹ããŒãïŒããšãã°ãMIFã§ã䜿çšã§ããããŸãã¯ç¬èªã®ãã©ã³ã¹ããŒãã䜿çšããïŒã䜿çšããŠãç¬èªã®äžæã®ããŒã¿åŠçãã§ãŒã³ãã·ãªã¢ã«åããã³åéã§ããŸãïŒãã±ããå¢çãå§çž®ãæå·åããã«ãã¹ã¬ããåŠçãªã©ã決å®ããŸãïŒã ãããè¡ãã«ã¯ãã¢ããªã±ãŒã·ã§ã³ãã³ãã¬ãŒãã§ã¯ãªããã¢ããªã±ãŒã·ã§ã³ã®åºæ¬ã¯ã©ã¹ïŒMif :: Application :: ApplicationïŒã䜿çšããŠãããŒã¿åŠçãã§ãŒã³ãŸãã¯ãã©ã³ã¹ããŒãã®å¿ èŠãªéšåãåå¥ã«æ±ºå®ããå¿ èŠããããŸãã
MIFãããžã§ã¯ãã®æåã®ããŒãžã§ã³ã«ã¯ãäºåå®çŸ©ãããã¢ããªã±ãŒã·ã§ã³ãã³ãã¬ãŒãã¯ãããŸããã§ããã äŸã¯ããã»ã©çãã¯èŠããŸããã§ããããããŒã¿åŠçãããŒãå®å šã«å¶åŸ¡ããããã«å¿ èŠãªå šãã¹ã瀺ããŸããã ãã§ãŒã³å šäœã¯ããããžã§ã¯ãã®æåã®ããŒãžã§ã³ïŒ MIF 1.0 ïŒã®äŸã«ç€ºãããŠããŸãã
ã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³
ã¯ã©ã€ã¢ã³ãåŽã§ã¯ãå ±ééšåã§å®çŸ©ãããŠãããã¹ãŠã®ãã®ã䜿çšãããŸãã
ã¯ã©ã€ã¢ã³ãã¯åãã¢ããªã±ãŒã·ã§ã³ãã¬ãŒã ã¯ãŒã¯ã§ãïŒãã®äŸã§ã¯å®çŸ©æžã¿ã®ã¢ããªã±ãŒã·ã§ã³ãã³ãã¬ãŒãã䜿çšããŸãïŒãã¯ã©ã¹/ãµãŒãã¹ã®ãªã¢ãŒããã¡ã¯ããªãèŠæ±ããããããéããŠç®çã®ãªããžã§ã¯ããäœæããããã®ã¡ãœãããåŒã³åºãããŸãã
// MIF #include <mif/application/tcp_service_client.h> #include <mif/common/log.h> // COMMON #include "common/id/service.h" #include "common/ps/imy_company.h" class Application : public Mif::Application::TcpServiceClient { public: using TcpServiceClient::TcpServiceClient; private: void ShowEmployees(Service::Data::Employees const &employees) const { // ... } // Mif.Application.TcpServiceClient virtual void Init(Mif::Service::IFactoryPtr factory) override final { auto service = factory->Create<Service::IMyCompany>(Service::Id::MyCompany); { Service::Data::Employee e; e.name = "Ivan"; e.lastName = "Ivanov"; e.age = 25; e.position = Service::Data::Position::Manager; auto const eId = service->AddEmployee(e); MIF_LOG(Info) << "Employee Id: " << eId; } { Service::Data::Employee e; e.name = "Petr"; e.lastName = "Petrov"; e.age = 30; e.position = Service::Data::Position::Developer; auto const eId = service->AddEmployee(e); MIF_LOG(Info) << "Employee Id: " << eId; } auto const &employees = service->GetEmployees(); ShowEmployees(employees); if (!employees.empty()) { auto id = std::begin(employees)->first; service->RemoveAccount(id); MIF_LOG(Info) << "Removed account " << id; auto const &employees = service->GetEmployees(); ShowEmployees(employees); try { MIF_LOG(Info) << "Removed again account " << id; service->RemoveAccount(id); } catch (std::exception const &e) { MIF_LOG(Warning) << "Error: " << e.what(); } } } }; int main(int argc, char const **argv) { return Mif::Application::Run<Application>(argc, argv); }
çµæ
ãµãŒããŒã¢ããªã±ãŒã·ã§ã³ã®çµæ
2017-08-09T14:01:23.404663 [INFO]: Starting network application on 0.0.0.0:55555 2017-08-09T14:01:23.404713 [INFO]: Starting server on 0.0.0.0:55555 2017-08-09T14:01:23.405442 [INFO]: Server is successfully started. 2017-08-09T14:01:23.405463 [INFO]: Network application is successfully started. Press 'Enter' for quit. 2017-08-09T14:01:29.032171 [INFO]: MyCompany 2017-08-09T14:01:29.041704 [INFO]: AddEmployee. Name: Ivan LastName: Ivanov Age: 25 Position: Manager 2017-08-09T14:01:29.042948 [INFO]: AddEmployee. Name: Petr LastName: Petrov Age: 30 Position: Developer 2017-08-09T14:01:29.043616 [INFO]: GetEmployees. 2017-08-09T14:01:29.043640 [INFO]: Id: 0 Name: Ivan LastName: Ivanov Age: 25 Position: Manager 2017-08-09T14:01:29.043656 [INFO]: Id: 1 Name: Petr LastName: Petrov Age: 30 Position: Developer 2017-08-09T14:01:29.044481 [INFO]: Removed employee account for Id: 0 Name: Ivan LastName: Ivanov Age: 25 Position: Manager 2017-08-09T14:01:29.045121 [INFO]: GetEmployees. 2017-08-09T14:01:29.045147 [INFO]: Id: 1 Name: Petr LastName: Petrov Age: 30 Position: Developer 2017-08-09T14:01:29.045845 [WARNING]: RemoveAccount. Employee with id 0 not found. 2017-08-09T14:01:29.046652 [INFO]: ~MyCompany 2017-08-09T14:02:05.766072 [INFO]: Stopping network application ... 2017-08-09T14:02:05.766169 [INFO]: Stopping server ... 2017-08-09T14:02:05.767180 [INFO]: Server is successfully stopped. 2017-08-09T14:02:05.767238 [INFO]: Network application is successfully stopped.
ã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ã®çµæ
2017-08-09T14:01:29.028821 [INFO]: Starting network application on 0.0.0.0:55555 2017-08-09T14:01:29.028885 [INFO]: Starting client on 0.0.0.0:55555 2017-08-09T14:01:29.042510 [INFO]: Employee Id: 0 2017-08-09T14:01:29.043296 [INFO]: Employee Id: 1 2017-08-09T14:01:29.044082 [INFO]: Employee. Id: 0 Name: Ivan LastName: Ivanov Age: 25 Position: Manager 2017-08-09T14:01:29.044111 [INFO]: Employee. Id: 1 Name: Petr LastName: Petrov Age: 30 Position: Developer 2017-08-09T14:01:29.044818 [INFO]: Removed account 0 2017-08-09T14:01:29.045517 [INFO]: Employee. Id: 1 Name: Petr LastName: Petrov Age: 30 Position: Developer 2017-08-09T14:01:29.045544 [INFO]: Removed again account 0 2017-08-09T14:01:29.046357 [WARNING]: Error: [Mif::Remote::Proxy::RemoteCall] Failed to call remote method "IMyCompany::RemoveAccount" for instance with id "411bdde0-f186-402e-a170-4f899311a33d". Error: RemoveAccount. Employee with id 0 not found. 2017-08-09T14:01:29.046949 [INFO]: Client is successfully started. 2017-08-09T14:01:29.047311 [INFO]: Network application is successfully started. Press 'Enter' for quit. 2017-08-09T14:02:02.901773 [INFO]: Stopping network application ... 2017-08-09T14:02:02.901864 [INFO]: Stopping client ... 2017-08-09T14:02:02.901913 [INFO]: Client is successfully stopped. 2017-08-09T14:02:02.901959 [INFO]: Network application is successfully stopped.
ã¯ããäŸå€ãããã»ã¹ã®å¢çãè¶ ããŠããŸã...
[WARNING]: Error: [Mif::Remote::Proxy::RemoteCall] Failed to call remote method "IMyCompany::RemoveAccount" for instance with id "411bdde0-f186-402e-a170-4f899311a33d". Error: RemoveAccount. Employee with id 0 not found.
ã¡ãã»ãŒãžãããèå¥å0ã®åŸæ¥å¡ã«é¢ããæ å ±ãåé€ããã¡ãœãããå床åŒã³åºãããããšãããããŸãããµãŒããŒã¯ããid 0ã®åŸæ¥å¡ãèŠã€ãããŸããããšããäŸå€ãå ±åããŠããµãŒããŒåŽã«ãã®ãããªã¬ã³ãŒãã¯ãããŸãã/
ãã®äŸã§ã¯ãã¯ã©ã€ã¢ã³ããšãµãŒããŒã®ããã»ã¹éçžäºäœçšã瀺ãããã©ã³ã¹ããŒãã«é¢é£ãããã¹ãŠã®è©³çŽ°ãšéä¿¡ããŒã¿ã®åœ¢åŒãå¯èœãªéãé ããŠããŸãã
ãã®äŸã¯ãMIFãããžã§ã¯ãã®åºç€ãšãªãããŒã¹ã®è¡šç€ºãå®äºããŸãã è¿œå æ©èœãå«ãŸããŸã
- åäžã®éå±€ã«çµ±åãããŠããªãå®è£ ããã€ã³ã¿ãŒãã§ã€ã¹ãèŠæ±ããæ©èœ ïŒMif :: Service :: IServiceããã®ç¶æ¿ã¯ã«ãŠã³ãããŸããïŒã
- ãµãŒãã¹éã®ã€ã³ã¿ãŒãã§ã€ã¹ã«ãã€ã³ã¿ãŒãšã¹ããŒããã€ã³ã¿ãŒãæž¡ããŸãã ã³ãŒã«ããã¯ã䜿çšãããµãŒãã¹ã®ããŸããŸãªå®è£ ã«åœ¹ç«ã€ãã®ã ããšãã°ããããªãã·ã¥/ãµãã¹ã¯ã©ã€ãã«åºã¥ããµãŒãã¹ã äŸã¯ã 蚪åè ãã¿ãŒã³ã®å®è£ ã§ãããã®äžéšã¯ç°ãªãããã»ã¹ã«ãããtcpãä»ããŠçžäºäœçšããŸãã
HTTP
ããã»ã¹ééä¿¡ã®äŸã§ã¯ãæ¢åã®TCPãã©ã³ã¹ããŒããHTTPãã©ã³ã¹ããŒãã«ç°¡åã«çœ®ãæããããšãã§ããŸãã curlããã©ãŠã¶ãªã©ã䜿ãæ £ããæ段ã䜿çšããŠãµãŒãã¹ã«ã¢ã¯ã»ã¹ã§ããŸãã
HTTPãµããŒãã«ãããJSON REST APIã䜿çšããŠåæã«WebãµãŒããŒã«ãªãããšãã§ãããµãŒãã¹ãæ§ç¯ã§ããåæã«C ++ã€ã³ã¿ãŒãã§ã€ã¹ãä»ãã以åã«å®èšŒãããçžäºäœçšããµããŒãã§ããŸãã
å€ãã®å Žåãå¿«é©æ§ã«ã¯å¶éã䌎ããŸãã HTTPãã©ã³ã¹ããŒãã䜿çšããå Žåã®ãã®å¶éã¯ãã€ã³ã¿ãŒãã§ã€ã¹ã«æž¡ãããã¡ãœãããã³ãŒã«ããã¯ã§ããªãããšã§ãã HTTPãã©ã³ã¹ããŒãã«åºã¥ããœãªã¥ãŒã·ã§ã³ã¯ããããªãã·ã¥/ãµãã¹ã¯ã©ã€ãã¢ããªã±ãŒã·ã§ã³ã®æ§ç¯ã«çŠç¹ãåãããŠããŸãããããã¯ãHTTPãä»ããäœæ¥ã«ã¯èŠæ±ãšå¿çã®ã¢ãããŒããé¢ä¿ããããã§ããã¯ã©ã€ã¢ã³ãã¯ãµãŒããŒã«èŠæ±ãéä¿¡ããå¿çãåŸ ã¡ãŸãã
MIFã§ææ¡ãããŠããTCPãã©ã³ã¹ããŒãã«ã¯ããã®ãããªå¶éã¯ãããŸãããã¯ã©ã€ã¢ã³ããšãµãŒããŒã®äž¡æ¹ãã¡ãœãããåŒã³åºãããšãã§ããŸãããã®å Žåãã¯ã©ã€ã¢ã³ããšãµãŒããŒã®åºå¥ããããŸãã«ãªããŸãããªããžã§ã¯ããçžäºã«éä¿¡ã§ãããã£ãã«ã衚瀺ãããäž¡åŽããã¡ãœãããåŒã³åºããŸããããã«ããããããªãã·ã¥/ãµãã¹ã¯ã©ã€ãã¢ãŒããã¯ãã£ãæ§ç¯ããããã®åæ¹åã®å¯Ÿè©±ãå¯èœã«ãªããŸããããã¯ãã€ã³ã¿ãŒããã»ã¹ã®äŸã§å®èšŒãããŸãã蚪åè ã
MIF HTTPã¯ãç¹ã«æ³šæãæã£ãŠããŸããæåã¯ãWebçšã®ããã¯ãšã³ããµãŒãã¹ã®éçºã«çŠç¹ãåœãŠãããŠããŸãããå°ããªHTTP WebãµãŒãã¹ãäœæããHTTPãä»ããŠãµãã©ã€ã€ããããŒã¿ãåä¿¡ããå¿ èŠãããããã®åŸã®ã¿ããã»ã¹éã§ã€ã³ã¿ãŒãã§ã€ã¹ãããŒã·ã£ãªã³ã°ãããšãã«ãã©ã³ã¹ããŒããšããŠHTTPã䜿çšããæ©èœãè¿œå ãããŸããããããã£ãŠãåçŽãªWebãµãŒãã¹ãã¯ã©ã€ã¢ã³ããäœæããæåã®äŸã瀺ããæåŸã«ãããã»ã¹éã§ã€ã³ã¿ãŒãã§ãŒã¹ã転éããããšããµããŒãããWebãµãŒããŒã®äŸã瀺ããŸãã
åçŽãªHTTP WebãµãŒããŒ
// MIF #include <mif/application/http_server.h> #include <mif/common/log.h> #include <mif/net/http/constants.h> class Application : public Mif::Application::HttpServer { public: using HttpServer::HttpServer; private: // Mif.Application.HttpServer virtual void Init(Mif::Net::Http::ServerHandlers &handlers) override final { handlers["/"] = [] (Mif::Net::Http::IInputPack const &request, Mif::Net::Http::IOutputPack &response) { auto data = request.GetData(); MIF_LOG(Info) << "Process request \"" << request.GetPath() << request.GetQuery() << "\"\t Data: " << (data.empty() ? std::string{"null"} : std::string{std::begin(data), std::end(data)}); response.SetCode(Mif::Net::Http::Code::Ok); response.SetHeader( Mif::Net::Http::Constants::Header::Connection::GetString(), Mif::Net::Http::Constants::Value::Connection::Close::GetString()); response.SetData(std::move(data)); }; } }; int main(int argc, char const **argv) { return Mif::Application::Run<Application>(argc, argv); }
äœæ¥ã確èªããã«ã¯ã次ã®ã³ãã³ãã䜿çšã§ããŸã
curl -iv -X POST "http://localhost:55555/" -d 'Test data'
æºåãæŽã£ãŠããã®ã¯ãçŽ30è¡ã®ã³ãŒããšãMIFã¢ããªã±ãŒã·ã§ã³ãã¬ãŒã ã¯ãŒã¯ã«åºã¥ããã«ãã¹ã¬ããHTTPãšã³ãŒãµãŒããŒã®ã¿ã§ããããã¯ãšã³ããšããŠlibeventã䜿çšãããŸããabãŠãŒãã£ãªãã£ã䜿çšããç°¡åãªãã¹ãã§ã¯ã1ç§ãããæ倧160Kã¯ãšãªã®å¹³åçµæãçæãããŸãããã¡ããããã¹ãŠã¯ãã¹ããå®è¡ãããããŒããŠã§ã¢ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããããã¯ãŒã¯ãªã©ã«äŸåããŸããããããæ¯èŒã®ããã«ãPythonãšGoã§ãåæ§ã®ããšãè¡ãããŸãããPythonãµãŒããŒã®åäœã¯2åé ããªããGoã®å Žåãçµæã¯äŸããã®ãµãŒããŒçµæã®10ïŒ ã ãå¹³åã§è¯ããªããŸãããããªããC ++éçºè ã§ãããPythonãšGoãããªãã«ãšã£ãŠç°è³ªã§ãããããããžã§ã¯ãã®ãã¬ãŒã ã¯ãŒã¯å ã®å éšåœä»€ã«ãã£ãŠå ¬åŒã«ä¿®æ£ããããããããªãä»ã®çç±ãããå ŽåãC ++ã®ã¿ã奜ãã§ãææ¡ããããœãªã¥ãŒã·ã§ã³ã䜿çšããŠé床ãšéçºæéã®é¢ã§è¯ãçµæãåŸãããšãã§ããŸã...
HTTPã¯ã©ã€ã¢ã³ã
ã¯ã©ã€ã¢ã³ãéšåã¯ãã¯ã©ã¹Mif :: Net :: Http :: Connectionã§è¡šãããŸããããã¯ãMIFã®C ++ã€ã³ã¿ãŒãã§ã€ã¹ãããŒã·ã£ãªã³ã°ããHTTPãã©ã³ã¹ããŒãã®åºç€ã§ãããããããããŸã§ã®ãšããããŒã·ã£ãªã³ã°ã«ã€ããŠã§ã¯ãããŸãã...ãã®ã¯ã©ã¹ã¯ãMIFãã€ã¯ããµãŒãã¹ã®ããã»ã¹éçžäºäœçšã®ã€ã³ãã©ã¹ãã©ã¯ãã£å šäœãšã¯å¥ã«äœ¿çšã§ããŸããããšãã°ãã¡ãã£ã¢ã³ã³ãã³ãã倩æ°äºå ±ãæ ªäŸ¡ãªã©ã®ãµãã©ã€ã€ã®ããŒã¿ãããŠã³ããŒãã§ããŸãã
äžèšã®ãšã³ãŒãµãŒãã¹ãå®è¡ãããšããã®ã¯ã©ã€ã¢ã³ãã§ã¢ã¯ã»ã¹ã§ããŸãã
// STD #include <cstdlib> #include <future> #include <iostream> #include <string> // MIF #include <mif/net/http/connection.h> #include <mif/net/http/constants.h> int main() { try { std::string const host = "localhost"; std::string const port = "55555"; std::string const resource = "/"; std::promise<std::string> promise; auto future = promise.get_future(); Mif::Net::Http::Connection connection{host, port, [&promise] (Mif::Net::Http::IInputPack const &pack) { if (pack.GetCode() == Mif::Net::Http::Code::Ok) { auto const data = pack.GetData(); promise.set_value({std::begin(data), std::end(data)}); } else { promise.set_exception(std::make_exception_ptr( std::runtime_error{ "Failed to get response from server. Error: " + pack.GetReason() })); } } }; auto request = connection.CreateRequest(); request->SetHeader(Mif::Net::Http::Constants::Header::Connection::GetString(), Mif::Net::Http::Constants::Value::Connection::Close::GetString()); std::string data = "Test data!"; request->SetData({std::begin(data), std::end(data)}); connection.MakeRequest(Mif::Net::Http::Method::Type::Post, resource, std::move(request)); std::cout << "Response from server: " << future.get() << std::endl; } catch (std::exception const &e) { std::cerr << "Error: " << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }
ããã¯ããšã©ãŒåŠçã«çŠç¹ãåœãŠãŠããªãåºæ¬çãªäŸã§ããåçŽãªã¯ã©ã€ã¢ã³ããéçºããèœåã瀺ããŠããŸãããã¡ãããããšãã°curlã©ã€ãã©ãªã«åºã¥ããŠäœãä»ã®ãã®ã䜿çšããæ¹ãè¯ãã§ãããæã«ã¯ç°¡åãªå Žåã«ã¯äžèšã®ã³ãŒãã§ååãããããŸããã
ãã¥ã¢ã«ã€ã³ã¿ãŒãã§ã€ã¹HTTP WebãµãŒããŒ
ãã®äŸã§ã¯ãMIFãããžã§ã¯ãã§ã®HTTPãµããŒããèŠçŽããŠããŸãããã®äŸã¯ããã©ãŠã¶ãŒãŸãã¯curlã䜿çšããŠã¢ã¯ã»ã¹ã§ããHTTP WebãµãŒããŒãšãC ++ã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠåäœãããã©ã³ã¹ããŒããšããŒã¿åœ¢åŒã«ã€ããŠäœãç¥ããããªãã¯ã©ã€ã¢ã³ãã瀺ããŠããŸãã以åãšåãMif :: Application :: HttpServerã¢ããªã±ãŒã·ã§ã³ãã¬ãŒã ã¯ãŒã¯ã䜿çšããŸãããã¢ã³ã¹ãã¬ãŒã·ã§ã³ã«ã¯ã次ã®ã³ãŒãã¹ãããããå¿ èŠã§ãããµã³ãã«å šäœã¯ãhttpã®äŸã®githubã§å ¥æã§ããŸãã
äžè¬éš
ã€ã³ã¿ãŒãã§ãŒã¹
namespace Service { struct IAdmin : public Mif::Service::Inherit<Mif::Service::IService> { virtual void SetTitle(std::string const &title) = 0; virtual void SetBody(std::string const &body) = 0; virtual std::string GetPage() const = 0; }; } // namespace Service
ã€ã³ã¿ãŒãã§ã€ã¹ã«ã¡ã¿æ å ±ãè¿œå ãããšããµãŒãã¹å®è£ ã®èå¥åã¯ãã¹ãŠãåè¿°ã®ããã»ã¹ééä¿¡ã®äŸã«äŒŒãŠããŸãã
ãµãŒããŒåŽ
ã¢ããªã±ãŒã·ã§ã³ã¯ã€ã€ãŒãã¬ãŒã
class Application : public Mif::Application::HttpServer { //... private: // Mif.Application.HttpService virtual void Init(Mif::Net::Http::ServerHandlers &handlers) override final { std::string const adminLocation = "/admin"; std::string const viewLocation = "/view"; auto service = Mif::Service::Create<Service::Id::Service>(viewLocation); auto webService = Mif::Service::Cast<Mif::Net::Http::IWebService>(service); auto factory = Mif::Service::Make<Mif::Service::Factory, Mif::Service::Factory>(); factory->AddInstance(Service::Id::Service, service); std::chrono::microseconds const timeout{10000000}; auto clientFactory = Service::Ipc::MakeClientFactory(timeout, factory); handlers.emplace(adminLocation, Mif::Net::Http::MakeServlet(clientFactory)); handlers.emplace(viewLocation, Mif::Net::Http::MakeWebService(webService)); } };
ãªãœãŒã¹ãã³ãã©ã¯çŽæ¥èšå®ãããªããªããŸããããè¿œå ã®ã©ãããŒã䜿çšããŠã次ã®ããšãã§ããŸãã
- ãªãœãŒã¹ã«ç°ãªããã³ãã©ãŒãè¿œå ããŸã
- ãªã¯ãšã¹ãããã£ããã¯ãšãªãã©ã¡ãŒã¿ãŒãšããŒã¿ãèªåçã«è§£æããŸã
- éžæãã圢åŒãžã®å¿çãèªåçã«ã·ãªã¢ã«åããŸã
- 2ã€ã®ã¢ãããŒããçµã¿åãããŸãããããããREST APIãä»ããŠHTTPã§äœæ¥ããC ++ã€ã³ã¿ãŒãã§ã€ã¹ãããŒã·ã£ãªã³ã°ãããµããŒãã®ããã¯ã©ã€ã¢ã³ãã§äœæ¥ããŸã
ãããã®æ©èœã¯ãã¹ãŠãMif :: Net :: Http :: WebServiceãšããåºæ¬ã¯ã©ã¹ã«å®è£ ãããŠããŸããã«ã¹ã¿ã ã¯ã©ã¹ã¯ãããç¶æ¿ããå¿ èŠããããŸãããªããªãããã¯çŽç²ãªä»®æ³ã¡ãœãããå«ããµãŒãã¹ã§ããããã®å®è£ ã¯ãã¬ãŒã ã¯ãŒã¯ã®ãµãŒãã¹ã³ãŒãã«é ãããŠããããã掟çã¯ã©ã¹ã®ã€ã³ã¹ã¿ã³ã¹ã¯ããã¡ã¯ããªã¡ãœããã«ãã£ãŠãã¹ãŠã®ãµãŒãã¹ãšåæ§ã«äœæããå¿ èŠããããŸãããµãŒãã¹ãHTTP WebãµãŒããŒãã³ãã©ãŒãšããŠäœ¿çšããã«ã¯ãMif :: Net :: Http :: MakeServleté¢æ°ã䜿çšããŠã©ãããŒãäœæããå¿ èŠããããŸãã
MIFãµãŒãã¹ãšWebãµãŒãã¹ã¯ç°ãªããµãŒãã¹ã§ããMIFãµãŒãã¹ã¯ãHTTPèŠæ±ãŸãã¯ä»ã®ãããã¯ãŒã¯èŠæ±ã®åŠçã®ã¿ãåŠçããå¿ èŠã®ãªãã€ã³ã¿ãŒãã§ã€ã¹ã®å®è£ ã¯ã©ã¹ãšããŠã®ã¿ç解ããå¿ èŠããããŸããWebãµãŒãã¹ã¯ãã§ã«ãã銎æã¿ã®ããæŠå¿µã§ããããããå¿ èŠã«å¿ããŠãMIFã§ã¯ãããããã¹ãŠãç°¡åã«1ã€ã®å šäœã«çµåãããæå®ã®äŸã§ç¢ºèªãããŠããŸãã
ãµãŒãã¹ãã³ãã©ãŒ
namespace Service { namespace Detail { namespace { class WebService : public Mif::Service::Inherit < IAdmin, Mif::Net::Http::WebService > { public: WebService(std::string const &pathPrefix) { AddHandler(pathPrefix + "/stat", this, &WebService::Stat); AddHandler(pathPrefix + "/main-page", this, &WebService::MainPage); } private: // ⊠// IAdmin virtual void SetTitle(std::string const &title) override final { // ... } // ⊠// Web hadlers Result<Mif::Net::Http::JsonSerializer> Stat() { // ... std::map<std::string, std::int64_t> resp; // Fill resp return resp; } Result<Mif::Net::Http::PlainTextSerializer> MainPage(Prm<std::string, Name("format")> const &format) { // ... } }; } // namespace } // namespace Detail } // namespace Service MIF_SERVICE_CREATOR ( ::Service::Id::Service, ::Service::Detail::WebService, std::string )
ããã€ãã®ç¹ã«æ³šæãåèµ·ããããšæããŸãã
- Mif::Service::Inherit . Mif::Service::Inherit . IAdmin , IWebService Mif::Net::Http::WebService, HTTP .
- . , - Mif::Net::Http::WebService , AddHandler. , /view/stat
- , . -. . .
- - . Prm. Prm , . Prm. , , ( stl , , list, vector, set). , timestamp , boost::posix_time. Content. . , Headers / Params. . http_crud
- å®è£ ã¯ã©ã¹ãäœæããããã®ãã¡ã¯ããªã¡ãœãããå®çŸ©ããå Žåãè¿œå ã®ãã©ã¡ãŒã¿ãŒãMIF_SERVICE_CREATORãã¯ãã«æž¡ãããŸããããã¯ãå®è£ ã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ãå¿ èŠããããŸãããã¯ãMIF_SERVICE_CREATORã®äœ¿çšã«ã€ããŠã¯äžèšã§èª¬æããŸããã
ã¯ã©ã€ã¢ã³ã
ã¯ã©ã€ã¢ã³ãã¯ãåè¿°ã®äŸãšå€§å·®ãããŸãããäŸå€ã¯ãäºåå®çŸ©ãããã¯ãšãªåŠçãã§ãŒã³ã®æ¬ åŠã§ããéçºè ãç¬èªã«äœæããŸããMIFã§HTTPãä»ããŠäœæ¥ããããã®å®çŸ©æžã¿ã®èŠæ±åŠçãã§ãŒã³ã¯ãããŸãããå®è£ æ©èœ...çç±ã«ã€ããŠã¯ãããããäœããåŸç¶ã®æçš¿ã§æžãããŸããå®å šãªã¯ã©ã€ã¢ã³ãã³ãŒãã¯httpã®äŸã§ãã
çµæ
çµã¿ç«ãŠããããµãŒããŒããã¹ãããã«ã¯ãäŸãã°curlã³ãã³ãã䜿çšããããã©ãŠã¶ãŒãããµãŒããŒãèµ·åããŠã¢ã¯ã»ã¹ããå¿ èŠããããŸã
curl "http://localhost:55555/view/main-page?format=text" curl "http://localhost:55555/view/main-page?format=html" curl "http://localhost:55555/view/main-page?format=json"
次ã«ã管çã€ã³ã¿ãŒãã§ã€ã¹ãä»ããŠã¢ã¯ã»ã¹ããŠããŒã¿ãå€æŽããã¯ã©ã€ã¢ã³ãã¢ããªã±ãŒã·ã§ã³ãèµ·åããcurlã³ãã³ããå床å®è¡ããŠãã ãããã¯ã©ã€ã¢ã³ãã«ãã£ãŠè¡ãããå€æŽãæ£åžžã«é©çšãããHTTPãä»ããŠè¿ãããçµæãå€æŽãããããšãããããŸãã
ããŒã¿ããŒã¹ãæäœãã
DBãªãã§ããã¯ã¢ãããããŠããŸããïŒããããªãã§ã¯ã©ãã§ããïŒå¿ ãããã§ã¯ãããŸãããããã£ãã«ãããŸãã...
çŸåšãMIFã§ã®ããŒã¿ããŒã¹ã®æäœã¯ãã¡ã¿æ å ±ã«äŸåããã«å®è£ ãããŠããŸãããããŸã§ã¯ãããŒã¿ããŒã¹ãæäœããã»ãŒå€å žçãªæ¹æ³ã§ããããã®éšåã¯ãããŒã¿ããŒã¹ã«äœããä¿åããå¿ èŠããããµãŒãã¹ãéçºããããã«å¿ èŠã§ããããããããã®éšåã®éçºã¯ãORMã®åºç€ãšãªããåã«è¿œå ããããã¹ãŠã®ã¡ã¿æ å ±ããã§ã«å®å šã«äœ¿çšãããããšãç®çãšããŠè¡ãããŸããã ORMãšã¯ãŸã é£æºããŠããŸãããå®è£ ããè©Šã¿ãããã€ããããŸãããéåžžã«é¢åã§ããããæè»æ§ããªãããšãå€æããŸãããç°¡æœããšæè»æ§ã®éã®åŠ¥åç¹ã¯ããã«å°éããORMã®æ¬¡ã®ããŒãžã§ã³ã«çŸãããšæããŸããã³ã³ãã€ã©ã«ããã€ãã®ãã§ãã¯ã転éã§ããããã«ãããã®ã§ãããçã®SQLã¯ãšãªæååã®åçŽãªãšã©ãŒãã¿ã€ããã¹ã«é¢é£ããããã°ã©ã ã®å®è¡æã«ãšã©ãŒããã£ããããããããŸããã
ORMã¯ãããŸããããå°ãå€å žçã§ã...
ããŒã¿ããŒã¹ã®æäœã«ã¯ããã€ãã®ã¹ããããå«ãŸããŠããŸãã
- ããŒã¿ããŒã¹æ¥ç¶ãªããžã§ã¯ãã®äœæ
- åä¿¡ããæ¥ç¶ãä»ãããªã¯ãšã¹ãã®å±¥è¡
- çµæåŠç
- ååŒ
JDBCïŒJavaïŒãŸãã¯C ++ã«äŒŒããã®ãªã©ã®ã©ãããŒã§äœæ¥ãã人ã¯ãããã§ã¯æ°ããããšãçºèŠããŸãããdb_clientã®
äŸã¯ãPostgreSQLãšSQLiteã®2ã€ã®DBMSã§ã®äœæ¥ã瀺ããŠããŸãã
HTTP CRUDãµãŒããŒ
http_crudã®äŸã¯ãHTTPãšããŒã¿ããŒã¹ã䜿çšãããã¢ã®è«ççãªçµè«ã§ããããã¯ãçžäºã«çŽæ¥å¯Ÿè©±ããªãWebçšã®åçŽãªãã€ã¯ããµãŒãã¹ã®å€å žã§ãã
WebãµãŒããŒã¯ã©ã¹ã«ã¯ããã¹ãŠã®åºæ¬çãªCRUDæäœã®ãã³ãã©ãŒãå«ãŸããŠããŸããããŒã¿ããŒã¹ã®æäœã¯ãã³ãã©ãŒå ã«ãããŸãããã®ãããªã³ãŒãã¯ãæ£åžžã«æ©èœããããŸããŸãªãµãŒãã¹ã§ããèŠãããŸããããããæåã®ã¹ã³ãŒãã«ãããããããDBMSãžã®äŸåãšããæ¬ ç¹ããããŸãããŸãããªã¬ãŒã·ã§ãã«ããŒã¿ããŒã¹ãæŸæ£ããŠNoSQLããŒã¿ããŒã¹ã«ã¢ã¯ã»ã¹ããå Žåã¯ããã¹ãŠã®ãã³ãã©ãŒã®ã³ãŒããã»ãŒå®å šã«æžãæããããŸããå€ãã®å®éã®ãããžã§ã¯ãã§ã¯ãããŒã¿ããŒã¹ã§ã®åæ§ã®äœæ¥ãé¿ããããšããŠããŸããé«ã¬ãã«ã®ããžãã¯æ©èœãåå¥ã®ãã¡ãµãŒãã«ç§»åããŸãããã¡ãµãŒãã¯éåžžãç¹å®ã®å®è£ ãæã€C ++ã€ã³ã¿ãŒãã§ã€ã¹ã§ãããããŠãããŒã¿ããŒã¹ã®çœ®ãæãã¯ãã€ã³ã¿ãŒãã§ãŒã¹ã®æ¬¡ã®å®è£ ãšãæ°ããèå¥åãæã€å®è£ ãã¡ã¯ããªãŒããã®èŠæ±ã«åž°çããŸãã蚌æ ã®ãã£ããã³ãæŒããŠããã®ã¢ãããŒãã¯äœåºŠã蚌æãããŠãããšèšããŸãã
ãããã«
äžèšã§èª¬æãããã¹ãŠïŒãªãã¬ã¯ã·ã§ã³ãã·ãªã¢ã«åãããã»ã¹ééä¿¡ãã€ã³ã¿ãŒãã§ã€ã¹ããŒã·ã£ãªã³ã°ãããŒã¿ããŒã¹ã®æäœãHTTPãµããŒã-ãã¹ãŠãããã€ã¯ããµãŒãã¹ã§å°èŠæš¡ã·ã¹ãã ãæ§ç¯ããæåŸã®äŸã«åæ ãããŸããããã®äŸã¯ãçžäºäœçšãã2ã€ã®ãã€ã¯ããµãŒãã¹ã§æ§æãããå°ããªãµãŒãã¹ã瀺ããŠããŸãã 1ã€ã®ãµãŒãã¹ã¯ããŒã¿ããŒã¹ãžã®ãã¡ãµãŒãã§ããã2çªç®ã®ãµãŒãã¹ã¯å€éšã¯ã©ã€ã¢ã³ãã«Json APIãæäŸããŸãããã®äŸã¯ã察象ãšãªãäŸhttp_crudã®ä¿®æ£ããŒãžã§ã³ã§ãããæçš¿ã®ãã¬ãŒã ã¯ãŒã¯ã§èª¬æããããã¹ãŠã®è«ççãªçµè«ïŒçµåïŒã§ãã
MIFã®äžéšãããšãã°db_clientã¯èæ ®ãããŠããŸããããã ãããŒã¿ããŒã¹ã®æäœã¯ä»ã®äŸã«ç€ºãããŠããŸããäŸã§ã¯ããµãŒãã¹ã®æäœïŒã€ã³ã¿ãŒãã§ãŒã¹å®è£ ïŒãéšåçã«åœ±é¿ãåããŸããã·ãªã¢ã«åãããŒã¿ããŒã¹åŠçãHTTPãµããŒããªã©ãMIFã®äžéšã¯ãã§ã«æ°åãã¹ããããŠããŸããéçºã®äžéšã®éšåã«å€ãã®æéãäžããããŠãããšããäºå®ã«ãããããããããã»ã¹ééä¿¡ã§ã¯æ€èšŒãšãããã°ã®æéãççž®ãããŠããŸããããšãã°ããããã«ã¯ãã€ã³ã¿ãŒãã§ã€ã¹ããã©ã¡ãŒã¿ãŒãšããŠå¥ã®ããã»ã¹ã«æž¡ããã¡ãœãããã³ãŒã«ããã¯ããããã®ãµããŒããå«ãŸããŸããæ¬è³ªçã«ãèªææ©èœããšã¯äœã§ãããç§ã¯èšªåè ã®äŸã§ç€ºãããŠããåæ§ã®ã¡ã«ããºã ãå®è£ ãããã£ãã®ã§ãããå°æ¥ããã®éšåãå®å šã§å®çžŸã®ãããããã°ããããœãªã¥ãŒã·ã§ã³ã«ããããšããèŠæããããŸãã
å°æ¥çã«ã¯ããããããæ瀺ãããè³æã«é¢å¿ãããå Žåãããšãã°ãMIFã®ãå éšããç¹å®ã®æ±ºå®ãè¡ãããçç±ã解決ããªããã°ãªããªãã¿ã¹ã¯ãthçŽãé©åããªãã£ããã®ãªã©ãããã«å«ãŸããªãã£ããã®ã§æçš¿ãç¶è¡ãããŸããŸãã¯ä»ã®åæ§ã®æ±ºå®ãç§ãèŠãŠããæ¬ ç¹ãç§ãå€æŽããã³æ¹åãããããšãªã©ããã®ãããžã§ã¯ãã¯ãããŒã ãããžã§ã¯ãããšããŠç»å ŽããŸããããé©ããããšã«ãç§ãããäžå¹Žè¿ã泚æãæã£ãŠãããããžã§ã¯ãã§ããä»ã«äœãæžãããšã«åé¡ã¯ãªãã¯ãã§ãã
èŠçŽãããšãC ++ãããžã§ã¯ãã®MIFãžã®ãªã³ã¯ãè€è£œããŸãã
ãæž èŽããããšãããããŸããã